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

let
  cfg = config.sydnix.deertopia.nginx;
in
{
  options.sydnix.deertopia.nginx = {
    enable = lib.mkEnableOption "Nginx";

    root = lib.mkOption {
      type = lib.types.path;
      description = "deertopia.net's root directory.";
      default = "/persist/deertopia.net";
    };

    group = lib.mkOption {
      type = lib.types.str;
      description =
        "The owning group of deertopia.net's root directory.";
      default = "nginx";
    };

    user = lib.mkOption {
      type = lib.types.str;
      description =
        "The owning user of deertopia.net's root directory.";
      default = "nginx";
    };

    vhosts = lib.mkOption {
      # NOTE: `name` shouldn't contain spaces.
      default = {};
      type = lib.types.attrsOf (lib.types.submodule ({ name, ... }: {
        options = {
          enable = lib.mkOption {
            description = "Enable ${name}.deertopia.net.";
            default = true;
            type = lib.types.boolean;
          };
          directory = lib.mkOption {
            description = "Host's root directory.";
            type = lib.types.nullOr lib.types.path;
            default = "${cfg.root}/${name}";
          };
          user = lib.mkOption {
            type = lib.types.nullOr lib.types.str;
            description = "The owning user of the host's root directory.";
            default = cfg.user;
          };
          group = lib.mkOption {
            type = lib.types.nullOr lib.types.str;
            description = "The owning group of the host's root directory.";
            default = cfg.group;
          };
          vhostName = lib.mkOption {
            type = lib.types.str;
            default = "${name}.deertopia.net";
          };
          vhost = lib.mkOption {
            description = ''
              Virtual host settings, passed directly to the NixOS's Nginx
              module.
            '';
            type = lib.types.anything;
          };
        };
      }));
    };
  };

  config = lib.mkIf cfg.enable {
    services.nginx.enable = true;

    networking.firewall.allowedTCPPorts = [
      80 # HTTP
      443 # HTTPS
    ];

    # With this section, virtual hosts declared through the Nginx NixOS module
    # will automatically request ACME SSL certificates and configure systemd
    # timers to renew the certificate if required.  See the article on the NixOS
    # wiki, from which I've nabbed the following snippet:
    # https://nixos.wiki/wiki/Nginx#Let.27s_Encrypt_certificates
    security.acme = {
      acceptTerms = true;
      defaults.email = "lomiskiam@gmail.com";
    };

    sydnix.impermanence.directories = [
      # Don't regenerate certs on reboot.
      "/var/lib/acme"
    ];

    services.nginx.virtualHosts =
      builtins.listToAttrs
        (builtins.map
          (k: {
            name = cfg.vhosts.${k}.vhostName;
            value = cfg.vhosts.${k}.vhost // {
              root = cfg.vhosts.${k}.directory;
            };
          })
          (builtins.attrNames cfg.vhosts));

    # services.nginx.virtualHosts."deertopia.net" = {
    #   root = "${cfg.www.root}/www";

    #   # addSSL = true;
    #   forceSSL = true;
    #   enableACME = true;

    #   locations."/" = {
    #     index = "index.html";
    #   };
    # };

    # system.activationScripts.initialiseDeertopiaRoot.text =
    #   let
    #     # FIXME: Use `lib.strings.toShellVar`.
    #     inherit (cfg) root group user;
    #   in ''
    #     mkdir -p "${root}"
    #     chown -R "${user}:${group}" "${root}"
    #     chmod -R 775 "${root}"

    #     ${lib.toShellVar "dirs"
    #       (builtins.catAttrs "directory" (builtins.attrValues cfg.vhosts))}
    #     for i in "''${dirs[@]}"; do
    #       mkdir -p "$i"
    #       chown -R "${user}:${group}" "$i"
    #       chmod -R 775 "$i"
    #     done
    # '';
  };
}
