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

with lib;
let
  primary-ip = "10.0.0.1";

  host-config = config.fudo.hosts.${config.instance.hostname};
  site-name = host-config.site;
  site = config.fudo.sites.${site-name};
  domain-name = host-config.domain;
  domain = config.fudo.domains.${domain-name};

  dns-proxy-port = 5335;

in {
  config = {

    boot.zfs.enableUnstable = true;

    networking = {
      interfaces = {
        enp1s0 = { useDHCP = true; };

        intif0 = {
          useDHCP = false;
          ipv4.addresses = [{
            address = primary-ip;
            prefixLength = 22;
          }];
        };
        intif1 = { useDHCP = false; };
        intif2 = { useDHCP = false; };
      };

      nameservers = [ "10.0.0.1" ];

      # FIXME: this should be automatic
      firewall.trustedInterfaces =
        [ "intif0" "intif1" "intif2" "lo" "docker0" ];

      nat = {
        enable = true;
        externalInterface = "enp1s0";
        internalInterfaces = [ "intif0" "intif1" "intif2" ];
      };
    };

    fudo = {
      hosts.limina.external-interfaces = [ "enp1s0" ];

      local-network = {
        enable = true;
        domain = domain-name;
        dns-servers = [ primary-ip ];
        gateway = primary-ip;
        dhcp-interfaces = [ "intif0" ];
        dns-listen-ips = [ primary-ip "127.0.0.1" "127.0.1.1" "::1" ];
        recursive-resolver = "${primary-ip} port 5353";
        network = site.network;
        dhcp-dynamic-network = site.dynamic-network;
        search-domains = [ domain-name "fudo.org" ];
        enable-reverse-mappings = true;
        network-definition = config.fudo.networks.${domain-name};
      };

      secrets.host-secrets.limina = {
        backplane-client-passwd = {
          source-file = /state/secrets/backplane-client/limina.passwd;
          target-file = "/srv/backplane/dns/client.passwd";
          user = config.fudo.client.dns.user;
        };

        host-keytab = {
          source-file = /state/secrets/kerberos/limina.keytab;
          target-file = "/etc/krb5.keytab";
          user = "root";
        };
      };

      client.dns = {
        enable = true;
        ipv4 = true;
        ipv6 = true;
        user = "fudo-client";
        external-interface = "enp1s0";
        password-file =
          config.fudo.secrets.host-secrets.limina.backplane-client-passwd.target-file;
      };

      garbage-collector = {
        enable = true;
        timing = "weekly";
      };

      secure-dns-proxy = {
        enable = true;
        listen-port = dns-proxy-port;
        upstream-dns =
          [ "https://1.1.1.1/dns-query" "https://1.0.0.1/dns-query" ];
        bootstrap-dns = "1.1.1.1";
        allowed-networks =
          [ "1.1.1.1/32" "1.0.0.1/32" "10.0.0.0/16" "localhost" "link-local" ];
        listen-ips = [ primary-ip ];
      };
    };

    virtualisation = {
      docker = {
        enable = true;
        autoPrune.enable = true;
        enableOnBoot = true;
      };

      oci-containers = {
        backend = "docker";
        containers = {
          pihole = {
            image = "pihole/pihole:v5.7";
            autoStart = true;
            ports = [ "5353:53/tcp" "5353:53/udp" "3080:80/tcp" ];
            environment = {
              # ServerIP = primary-ip;
              VIRTUAL_HOST = "dns-hole.sea.fudo.org";
              DNS1 = "${primary-ip}#${toString dns-proxy-port}";
            };
            volumes = [
              "/srv/pihole/etc-pihole/:/etc/pihole/"
              "/srv/pihole/etc-dnsmasq.d/:/etc/dnsmasq.d/"
            ];
          };
        };
      };
    };

    # Support for statelessness
    environment.etc = {
      nixos.source = "/state/nixos";
      adjtime.source = "/state/etc/adjtime";
      NIXOS.source = "/state/etc/NIXOS";
      machine-id.source = "/state/etc/machine-id";
      "host-config.nix".source = "/state/etc/host-config.nix";
      ## This should be handled by nixops deploy
      # "krb5.keytab" = {
      #   source = "/state/etc/limina.keytab";
      #   user = "root";
      #   mode = "0400";
      # };
    };

    boot.initrd.postDeviceCommands = lib.mkAfter ''
      ${pkgs.zfs}/bin/zfs rollback -r zroot/transient/root@blank
    '';

    security.sudo.extraConfig = ''
      # rollback results in sudo lectures after each reboot
      Defaults lecture = never
    '';

    systemd.tmpfiles.rules = [
      "L /root/.gnupg - - - - /state/root/gnupg"
      "L /root/.emacs.d - - - - /state/root/emacs.d"
      "L /root/.ssh/id_rsa - - - - /state/root/ssh/id_rsa"
      "L /root/.ssh/id_rsa.pub - - - - /state/root/ssh/id_rsa.pub"
      "L /root/.ssh/known_hosts - - - - /state/root/ssh/known_hosts"
      "L /etc/ssh/ssh_host_ed25519_key - - - - /state/ssh/ssh_host_ed25519_key"
      "L /etc/ssh/ssh_host_rsa_key - - - - /state/ssh/ssh_host_rsa_key"
    ];

    security.acme.certs."sea-camera.fudo.link".email = "niten@fudo.org";

    networking.firewall.allowedTCPPorts = [ 80 443 ];

    systemd.services.nginx.requires = [ "bind.service" ];

    services = {
      nginx = {
        enable = true;
        recommendedGzipSettings = true;
        recommendedOptimisation = true;
        recommendedProxySettings = true;

        virtualHosts = {
          "dns-hole.${domain-name}" = {
            serverAliases = [
              "pi-hole.${domain-name}"
              "pihole.${domain-name}"
              "hole.${domain-name}"
              "pi-hole"
              "pihole"
              "dns-hole"
              "hole"
            ];

            locations."/" = { proxyPass = "http://127.0.0.1:3080"; };
          };

          "sea-camera.fudo.link" = {
            enableACME = true;
            forceSSL = true;

            locations."/" = {
              # proxyPass = "http://cargo.sea.fudo.org:5000/webman/3rdparty/SurveillanceStation/";
              proxyPass = "http://cargo.sea.fudo.org:5000/";

              extraConfig = ''
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "Upgrade";

                proxy_set_header Host $host;
                # proxy_set_header X-Real-IP $remote_addr;
                # proxy_set_header X-Forwarded-By $server_addr:$server_port;
                # proxy_set_header X-Forwarded-For $remote_addr;
                # proxy_set_header X-Forwarded-Proto $scheme;
              '';
            };
          };

          # "sea-camera-od.fudo.link" = {
          #   enableACME = true;
          #   forceSSL = true;

          #   locations."/" = {
          #     proxyPass = "http://panopticon-od.sea.fudo.org";

          #     extraConfig = ''
          #       proxy_http_version 1.1;
          #       proxy_set_header Upgrade $http_upgrade;
          #       proxy_set_header Connection "Upgrade";

          #       proxy_set_header Host $host;
          #       proxy_set_header X-Real-IP $remote_addr;
          #       proxy_set_header X-Forwarded-By $server_addr:$server_port;
          #       proxy_set_header X-Forwarded-For $remote_addr;
          #       proxy_set_header X-Forwarded-Proto $scheme;
          #     '';
          #   };
          # };
        };
      };

      openssh = {
        hostKeys = [
          {
            path = "/state/ssh/ssh_host_ed25519_key";
            type = "ed25519";
          }
          {
            path = "/state/ssh/ssh_host_rsa_key";
            type = "rsa";
            bits = 4096;
          }
        ];
      };
    };
  };
}