{ config, pkgs, ... }:

let
  c3d2MacAddress = "00:0b:ad:00:1d:ea";

in
{
  c3d2.deployment.server = "server10";
  microvm = {
    mem = 1 * 1024;
    vcpu = 2;
    # add a network interface in c3d2 for mDNS
    interfaces = [{
      type = "tap";
      id = builtins.substring 0 15 "c3d2-${config.networking.hostName}";
      mac = c3d2MacAddress;
    }];
  };

  networking.hostName = "home-assistant";
  systemd.network = {
    links."40-c3d2" = {
      matchConfig.MACAddress = c3d2MacAddress;
      # rename interface to net name
      linkConfig.Name = "c3d2";
    };
    networks."40-c3d2" = {
      matchConfig.MACAddress = c3d2MacAddress;
      networkConfig = {
        LinkLocalAddressing = "yes";
        IPv6AcceptRA = "no";
      };
    };
  };

  services = {
    avahi.enable = true;

    home-assistant = {
      enable = true;
      config = {
        binary_sensor = [
          {
            platform = "rest";
            name = "Turmlabor";
            unique_id = "status_turmlabor_dresden";
            resource = "https://turmlabor.de/spaces.api";
            method = "GET";
            scan_interval = 60;
            verify_ssl = true;
            value_template = "{{ value_json['state']['open'] }}";
            device_class = "door";
          }
          {
            platform = "rest";
            name = "c3d2";
            unique_id = "status_c3d2";
            resource = "https://c3d2.de/spaceapi.json";
            method = "GET";
            scan_interval = 60;
            verify_ssl = true;
            value_template = "{{ value_json['state']['open'] }}";
            device_class = "door";
          }
        ];
        default_config = { }; # yes, this is required...
        automation = "!include automations.yaml";
        homeassistant = {
          auth_providers = [
            {
              type = "command_line";
              command =
                # the script is not inheriting PATH from home-assistant
                pkgs.resholve.writeScript "ldap-auth-sh" {
                  fake.external = [ "on_auth_failure" "on_auth_success" ];
                  inputs = with pkgs; [ coreutils curl gnugrep gnused openldap ];
                  interpreter = "${pkgs.bash}/bin/bash";
                  keep."source:$CONFIG_FILE" = true;
                } (builtins.readFile "${pkgs.fetchFromGitHub {
                  owner = "bob1de";
                  repo = "ldap-auth-sh";
                  rev = "819f9233116e68b5af5a5f45167bcbb4ed412ed4";
                  sha256 = "sha256-+QjRP5SKUojaCv3lZX2Kv3wkaNvpWFd97phwsRlhroY=";
                }}/ldap-auth.sh");
              args =
                let
                  inherit (config.security) ldap;
                  sed = "${pkgs.gnused}/bin/sed";
                in
                [
                  # https://github.com/bob1de/ldap-auth-sh/blob/master/examples/home-assistant.cfg
                  (pkgs.writeText "config.cfg" /* shell */ ''
                    ATTRS="${ldap.userField}"
                    CLIENT="ldapsearch"
                    DEBUG=0
                    FILTER="${ldap.groupFilter "home-assistant"}"
                    NAME_ATTR="${ldap.userField}"
                    SCOPE="base"
                    SERVER="ldaps://${ldap.domainName}"
                    USERDN="uid=$(ldap_dn_escape "$username"),${ldap.userBaseDN}"
                    BASEDN="$USERDN"

                    on_auth_success() {
                      # print the meta entries for use in HA
                      if [ ! -z "$NAME_ATTR" ]; then
                        name=$(echo "$output" | ${sed} -nr "s/^\s*$NAME_ATTR:\s*(.+)\s*\$/\1/Ip")
                        [ -z "$name" ] || echo "name=$name"
                      fi
                    }
                  '')
                ];
              meta = true;
            }
            # default authentication is required for the first step of onboarding
            # { type = "homeassistant"; }
          ];
          latitude = "51.08105";
          longitude = "13.72867";
          name = "C3D2";
          temperature_unit = "C";
          time_zone = config.time.timeZone;
          unit_system = "metric";
        };
        http = rec {
          # TODO: turn on when the public-access-proxy is using PROXY PROTOCOL
          # ip_ban_enabled = true;
          # login_attempts_threshold = 5;
          server_host = [
            "127.0.0.1"
            "::1"
          ];
          trusted_proxies = server_host;
          use_x_forwarded_for = true;
        };
      };
      extraComponents = [
        # defaults plus required for onboarding
        "backup"
        "default_config"
        "esphome"
        "met"
        "radio_browser"
        # extra things we use
        "wled"
      ];
      package = (pkgs.home-assistant.override {
        # those tests take a long(er) time and can't be sped up with pytest-xdist
        packageOverrides = final: prev: let
          noTests = {
            doCheck = false;
            doInstallCheck = false;
          };
        in {
          aws-sam-translator = prev.aws-sam-translator.overrideAttrs (_: noTests);
          moto = prev.moto.overrideAttrs (_: noTests);
        };
      }).overrideAttrs (_: {
        doCheck = false;
        doInstallCheck = false;
      });
    };

    nginx = {
      enable = true;
      virtualHosts."home-assistant.hq.c3d2.de" = {
        forceSSL = true;
        enableACME = true;
        locations."/" = {
          proxyPass = "http://127.0.0.1:${toString config.services.home-assistant.config.http.server_port}";
          proxyWebsockets = true;
        };
      };
    };

    portunus.addToHosts = true;
  };

  sops = {
    defaultSopsFile = ./secrets.yaml;
  };

  system.stateVersion = "22.11";
}
