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

with lib;

let cfg = config.sydnix.deertopia.webdav;
in {
  options = {
    sydnix.deertopia.webdav = {
      enable = mkEnableOption "Deertopia's WebDAV server";

      port = lib.mkOption {
        default = 22016;
        type = lib.types.port;
        description = ''
          The internal WebDAV port.  The actual server will be hosted at
          https://dav.deertopia.net/.
        '';
      };

      user = lib.mkOption {
        default = "webdav";
        type = lib.types.str;
      };

      group = lib.mkOption {
        default = "webdav";
        type = lib.types.str;
      };
    };
  };

  config = mkIf cfg.enable {
    users.users.${cfg.user} = {
      isSystemUser = true;
      group = cfg.group;
    };

    users.groups.${cfg.group} = {};

    systemd.services.webdav =
      let htpasswdFile = "/run/secrets/webdav-htpasswd";
          directory = "/var/lib/webdav";
      in {
        description = "Deertopia's WebDAV server";
        after = [ "network.target" ];
        wantedBy = [ "multi-user.target" ];
        script = ''
          ${pkgs.rclone}/bin/rclone serve webdav \
            --addr ":${builtins.toString cfg.port}" \
            --htpasswd "${htpasswdFile}" "${directory}"
        '';
        serviceConfig = {
          User = cfg.user;
          Group = cfg.group;
          Restart = "always";
        };
        unitConfig = {
          StateDirectory = "webdav";
        };
      };

    # Without this, Nginx will attempt redirections to https://localhost, which
    # is not okay because localhost does not have any associated certs!
    # See: https://forum.seafile.com/t/seafdav-move-command-causing-502/11582/26
    services.nginx.appendHttpConfig = ''
      map $http_destination $http_destination_webdav {
        ~*https://(.+) http://$1;
        default $http_destination;
      }
    '';

    systemd.tmpfiles.settings."50-var-lib-webdav" =
      let
        e =
          let x = { inherit (cfg) user group; mode = "2775"; };
          in { z = x; v = x; };
      in {
        "/var/lib/webdav/~msyds/org" = e;
        "/var/lib/webdav/~msyds/zotero" = e;
      };

    sydnix.sops.secrets.webdav-htpasswd = {
      owner = cfg.user;
      mode = "0600";
    };

    sydnix.impermanence.directories = [
      "/var/lib/webdav"
    ];

    sydnix.deertopia.nginx.vhosts."dav".vhost = {
      forceSSL = true;
      enableACME = true;
      locations."/" = {
        extraConfig = ''
          proxy_set_header Host $host;
          proxy_set_header X-Forwarded-For $remote_addr;
          # See previous note regarding the HTTPS -> HTTP redirection.
          proxy_set_header Destination $http_destination_webdav;

          # Increase limit of upload sizes.
          client_max_body_size 20G;

          proxy_pass "http://localhost:${builtins.toString cfg.port}";
        '';
      };
    };
  };
}
