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

with lib;
let
  cfg = config.fudo.secure-dns-proxy;

in {
  options.fudo.secure-dns-proxy = {
    enable = mkEnableOption "Enable a DNS server using an encrypted upstream source.";

    port = mkOption {
      type = types.port;
      description = "Port on which to listen for DNS queries.";
      default = 53;
    };

    upstream-dns = mkOption {
      type = with types; listOf str;
      description = ''
        The upstream DNS services to use, in a format useable by dnsproxy.

        See: https://github.com/AdguardTeam/dnsproxy
      '';
      default = ["https://cloudflare-dns.com/dns-query"];
    };

    bootstrap-dns = mkOption {
      type = types.str;
      description = "A simple DNS server from which HTTPS DNS can be bootstrapped, if necessary.";
      default = "1.1.1.1";
    };

    listen-ips = mkOption {
      type = with types; listOf str;
      description = "A list of local IP addresses on which to listen.";
      default = ["0.0.0.0"];
    };
  };

  config = mkIf cfg.enable {
    environment.systemPackages = with pkgs; [
      dnsproxy
    ];

    systemd.services.secure-dns-proxy = {
      enable = true;
      wantedBy = [ "multi-user.target" ];
      after = [ "network.target" ];
      description = "DNS Proxy for secure DNS lookups";
      serviceConfig = let
        upstreams = map (upstream: "-u ${upstream}") cfg.upstream-dns;
        upstream-line = concatStringsSep " " upstreams;
        listen-line = concatStringsSep " "
          (map (listen: "-l ${listen}") cfg.listen-ips);
        cmd = "${pkgs.dnsproxy}/bin/dnsproxy -p ${toString cfg.port} ${upstream-line} ${listen-line} -b ${cfg.bootstrap-dns}";

      in {
        ExecStart = cmd;
      };
    };
  };
}