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

with lib;

let
  cfg = config.roles.rclone-mount;

  # Generate systemd service for a single mount
  mkMountService = name: mountCfg: {
    description = "rclone mount for ${name}";
    after = [ "network-online.target" ];
    wants = [ "network-online.target" ];
    wantedBy = [ "multi-user.target" ];

    # Wait for parent mount points (e.g., ZFS pools) to be available
    unitConfig = mkIf (mountCfg.requiresMountsFor != []) {
      RequiresMountsFor = mountCfg.requiresMountsFor;
    };

    serviceConfig = {
      Type = "notify";
      ExecStartPre = "${pkgs.coreutils}/bin/mkdir -p ${mountCfg.mountPoint}";
      ExecStart = concatStringsSep " " ([
        "${pkgs.rclone}/bin/rclone mount"
        ":webdav:${mountCfg.remotePath}"
        "${mountCfg.mountPoint}"
        "--webdav-url=${mountCfg.webdavUrl}"
        "--webdav-vendor=${mountCfg.webdavVendor}"
        "--webdav-user=${mountCfg.username}"
        "--allow-other"
        "--vfs-cache-mode=${mountCfg.vfsCacheMode}"
        "--dir-cache-time=${mountCfg.dirCacheTime}"
        "--poll-interval=${mountCfg.pollInterval}"
        "--log-level=${mountCfg.logLevel}"
      ] ++ mountCfg.extraArgs);
      ExecStop = "${pkgs.fuse}/bin/fusermount -uz ${mountCfg.mountPoint}";
      Restart = "on-failure";
      RestartSec = "10s";
      EnvironmentFile = mountCfg.environmentFile;
    };
  };
in
{
  options.roles.rclone-mount = {
    enable = mkEnableOption "Enable rclone WebDAV mounts";

    mounts = mkOption {
      type = types.attrsOf (types.submodule {
        options = {
          webdavUrl = mkOption {
            type = types.str;
            description = "WebDAV server URL (e.g., https://webdav.torbox.app)";
          };

          webdavVendor = mkOption {
            type = types.enum [ "other" "nextcloud" "owncloud" "sharepoint" "sharepoint-ntlm" "fastmail" ];
            default = "other";
            description = "WebDAV server vendor for optimizations";
          };

          username = mkOption {
            type = types.str;
            description = "WebDAV username (often email address)";
          };

          environmentFile = mkOption {
            type = types.path;
            description = ''
              Path to environment file containing RCLONE_WEBDAV_PASS.
              The password should be obscured using: rclone obscure <password>
              File format: RCLONE_WEBDAV_PASS=<obscured_password>
            '';
          };

          mountPoint = mkOption {
            type = types.str;
            description = "Local mount point path";
          };

          remotePath = mkOption {
            type = types.str;
            default = "/";
            description = "Remote path on WebDAV server to mount";
          };

          vfsCacheMode = mkOption {
            type = types.enum [ "off" "minimal" "writes" "full" ];
            default = "full";
            description = ''
              VFS cache mode. For streaming media, 'full' is recommended.
              - off: No caching (direct reads/writes)
              - minimal: Cache open files only
              - writes: Cache writes and open files
              - full: Full caching of all files
            '';
          };

          dirCacheTime = mkOption {
            type = types.str;
            default = "5m";
            description = "Time to cache directory entries";
          };

          pollInterval = mkOption {
            type = types.str;
            default = "1m";
            description = "Poll interval for remote changes";
          };

          logLevel = mkOption {
            type = types.enum [ "DEBUG" "INFO" "NOTICE" "ERROR" ];
            default = "INFO";
            description = "rclone log level";
          };

          extraArgs = mkOption {
            type = types.listOf types.str;
            default = [];
            description = "Extra arguments to pass to rclone mount";
          };

          requiresMountsFor = mkOption {
            type = types.listOf types.str;
            default = [];
            description = ''
              List of mount points that must be available before this service starts.
              Use this when the mount point's parent is on a ZFS pool or other filesystem
              that may not be mounted at boot time.
              Example: [ "/media" ] to wait for the media ZFS pool to mount.
            '';
          };
        };
      });
      default = {};
      description = "Attribute set of rclone WebDAV mounts to configure";
    };
  };

  config = mkIf cfg.enable {
    # Ensure FUSE is available
    environment.systemPackages = [ pkgs.rclone pkgs.fuse ];
    programs.fuse.userAllowOther = true;

    # Create systemd services for each mount
    systemd.services = mapAttrs' (name: mountCfg:
      nameValuePair "rclone-mount-${name}" (mkMountService name mountCfg)
    ) cfg.mounts;
  };
}
