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

with pkgs;

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

  # Add a swap file
  swapDevices = [{
    device = "/swapfile";
    size = 4096;
  }];

  # Configure basic SSH access
  services.openssh = {
    enable = true;
    permitRootLogin = "yes";
  };

  # Cleanup tmp on startup
  boot.cleanTmpDir = true;

  # Create coolneng user
  users.users.coolneng = {
    isNormalUser = true;
    home = "/home/coolneng";
    extraGroups = [ "wheel" "docker" ];
    openssh.authorizedKeys.keys = [
      "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFRqINHR7/zc+c3/PuR+NeSsBHXXzBiEtFWSK6QaxQTW coolneng@panacea"
    ];
    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
  boot.kernel.sysctl = { "fs.inotify.max_user_watches" = 204800; };

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

  # NixOS version
  system.stateVersion = "22.05";

  # Specify secrets
  age = {
    secrets.wireguard.file = secrets/wireguard.age;
    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";
    };
    identityPaths = [ "/home/coolneng/.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}";
    };
  };

  # 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
  ];

}