{ config, lib, ... }:

let
  # Function to generate CoreDNS config for a single vhost
  generateCoreDNSConfigForVhost = domain: conf:
    let
      # Retrieve architect's IP on each interface
      interfaceConfigs = builtins.map
        (iface:
          let
            architectIP = config.architect.networks.${iface}.devices.architect.address;
            interfaceNet = config.architect.networks.${iface}.net;
          in
          ''
            ${domain} {
              view ${iface} {
                expr incidr(client_ip(), '${interfaceNet}')
              }

              template IN A ${domain} {
                answer "${domain}. 60 IN A ${architectIP}"
              }
              template IN HTTPS ${domain} {
                answer "${domain}. 60 IN HTTPS 1 . ipv4hint=\"${architectIP}\""
              }
              cache
              log
            }
          ''
        )
        conf.dnsInterfaces;
    in
    lib.concatStringsSep "\n" interfaceConfigs;
in
{
  services = {
    coredns = {
      enable = true;
      config = ''
        ${lib.concatStringsSep "\n" (lib.mapAttrsToList generateCoreDNSConfigForVhost config.architect.vhost)}
          
        . {
          cache
          forward . 127.0.0.1:${toString config.services.adguardhome.settings.dns.port}
        }
      '';
    };

    adguardhome = {
      enable = true;
      settings = {
        bind_port = 5354;
        dns = {
          port = 5300;
        };
        upstream_dns = [
          "tls://architect.d65174.dns.nextdns.io"
          "https://dns.nextdns.io/d65174/architect"
        ];
      };
    };

    dnscrypt-proxy2 = {
      enable = true;
      settings = {
        listen_addresses = [ "127.0.0.1:5354" ];
        ipv4_servers = true;
        ipv6_servers = false;
        block_ipv6 = true;
        dnscrypt_servers = true;
        doh_servers = true;
        require_nolog = true;
        require_nofilter = true;
        timeout = 350;
        lb_strategy = "p4";
        lb_estimator = true;
        ignore_system_dns = true;
        fallback_resolvers = [ "1.1.1.1:53" "9.9.9.9:53" ];
        cache_min_ttl = 60;
        cache_max_ttl = 360;
      };
    };
  };
}