{ config, inputs, pkgs, lib, ... }:

with pkgs;

{
  # Declare system packages
  environment.systemPackages = [
    libraspberrypi
    htop
    neovim
    git
    inputs.agenix.packages.aarch64-linux.default
  ];

  # Configure basic SSH access
  services.openssh = {
    enable = true;
    settings = {
      PermitRootLogin = "yes";
      PasswordAuthentication = false;
    };
  };

  # Cleanup tmp on startup
  boot.tmp.cleanOnBoot = true;

  # Create coolneng user
  users.users.coolneng = {
    isNormalUser = true;
    home = "/home/coolneng";
    extraGroups = [ "wheel" "docker" ];
    openssh.authorizedKeys.keys = [
      # panacea
      "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFRqINHR7/zc+c3/PuR+NeSsBHXXzBiEtFWSK6QaxQTW coolneng@panacea"
      # caravanserai
      "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPTBWNtNp+vI2So4vISZX/yQv754ZzXqobFgUP3zk4FY zion"
    ];
    shell = "${fish}/bin/fish";
  };

  # Set neovim as default editor
  programs.neovim = {
    enable = true;
    defaultEditor = true;
  };

  # Set timezone and synchronize NTP
  time.timeZone = "Europe/Brussels";
  services.timesyncd.enable = true;

  # Enable ZFS support
  boot.supportedFilesystems = [ "zfs" ];

  # Don't import encrypted datasets
  boot.zfs.requestEncryptionCredentials = false;

  # Scrub zpool monthly
  services.zfs.autoScrub = {
    enable = true;
    interval = "monthly";
  };

  # Run Nix garbage collector, while avoiding recompilation and enable flakes
  nix = {
    settings = {
      auto-optimise-store = true;
      experimental-features = [ "nix-command" "flakes" ];
    };
    gc = {
      automatic = true;
      options = "--delete-older-than 14d";
      dates = "Mon 03:00";
    };
    extraOptions = ''
      keep-outputs = true
      keep-derivations = true
      gc-keep-outputs = true
    '';
  };

  # Use same version of nixpkgs for nix-shell
  nix.nixPath = let path = toString ./.;
  in [ "nixpkgs=${inputs.nixpkgs}" "nixos-config=${path}/configuration.nix" ];

  # Configure fish shell
  programs.fish.enable = true;
  users.users.root = {
    shell = "${fish}/bin/fish";
    openssh.authorizedKeys.keys = [
      "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFRqINHR7/zc+c3/PuR+NeSsBHXXzBiEtFWSK6QaxQTW coolneng@panacea"
    ];
  };

  # Keep logs for a week
  services.journald.extraConfig = "MaxRetentionSec=1week";

  # Increase inotify limits and maximum buffer size
  boot.kernel.sysctl = {
    "fs.inotify.max_user_watches" = 204800;
    "net.core.rmem_max" = 2500000;
    "net.core.wmem_max" = 2500000;
  };

  # MOTD message
  programs.fish.interactiveShellInit = "${./scripts/motd.sh}";

  # NixOS version
  system.stateVersion = "22.05";

  # Specify secrets
  age = {
    secrets.wireguard = {
      file = secrets/wireguard.age;
      owner = "systemd-network";
      group = "systemd-network";
    };
    secrets.syncthing.file = secrets/syncthing.age;
    secrets.msmtp.file = secrets/msmtp.age;
    secrets.gitea = {
      file = secrets/gitea.age;
      owner = "gitea";
      group = "gitea";
    };
    secrets.ddclient.file = secrets/ddclient.age;
    secrets.miniflux = {
      file = secrets/miniflux.age;
      owner = "miniflux";
      group = "miniflux";
    };
    secrets.git = {
      file = secrets/git.age;
      owner = "coolneng";
      group = "users";
    };
    # HACK The owner and group is set by systemd due to the use of DynamicUser
    secrets.dendrite = {
      file = secrets/dendrite.age;
      owner = "63026";
      group = "63026";
    };
    secrets.dendrite-postgres = {
      file = secrets/dendrite-postgres.age;
      owner = "63026";
      group = "63026";
    };
    secrets.telegram = {
      file = secrets/telegram.age;
      owner = "matrix-as-telegram";
      group = "matrix-as-telegram";
    };
    secrets.mqtt-sender = {
      file = secrets/mqtt-sender.age;
      owner = "mosquitto";
      group = "mosquitto";
    };
    secrets.mqtt-receiver = {
      file = secrets/mqtt-receiver.age;
      owner = "mosquitto";
      group = "mosquitto";
    };
    secrets.nightscout = {
      file = secrets/nightscout.age;
      owner = "coolneng";
      group = "podman";
    };
    secrets.facebook = {
      file = secrets/facebook.age;
      owner = "matrix-as-facebook";
      group = "matrix-as-facebook";
    };
    secrets.signal = {
      file = secrets/signal.age;
      owner = "matrix-as-signal";
      group = "matrix-as-signal";
    };
    identityPaths = [ "/etc/ssh/id_ed25519" ];
  };

  # Auto-upgrade the system
  system.autoUpgrade = {
    enable = true;
    flake = "/home/coolneng/system";
    flags = [
      "--update-input"
      "agenix"
      "--update-input"
      "nixpkgs"
      "--commit-lock-file"
    ];
  };

  # Configure git for auto-upgrade
  programs.git = {
    enable = true;
    config = {
      user.name = "coolneng";
      user.email = "akasroua@gmail.com";
      safe.directory = "/home/coolneng/system";
      credential.helper = "store --file ${config.age.secrets.git.path}";
    };
  };

  # Disable man pages
  documentation.man.enable = false;

  # Import other configuration modules
  imports = [
    ./modules/hardware-configuration.nix
    ./modules/networking.nix
    ./modules/datasync.nix
    ./modules/webstack.nix
    ./modules/devops.nix
    ./modules/monitoring.nix
    ./modules/periodic.nix
    ./modules/communication.nix
    ./modules/information.nix
    ./modules/device.nix
    ./modules/containers.nix
  ];

}