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

with lib;

let
  cfg = config.roles.btrfs;
in
{
  options.roles.btrfs = {
    enable = mkEnableOption "Enable btrfs filesystem management";
    
    filesystems = mkOption {
      type = types.attrsOf (types.submodule {
        options = {
          # Filesystem-level maintenance options
          scrub = {
            enable = mkOption { 
              type = types.bool; 
              default = true;
              description = "Enable automatic scrubbing for this filesystem";
            };
            interval = mkOption { 
              type = types.str; 
              default = "weekly";
              description = "Scrub interval (systemd timer format)";
            };
          };
          deduplication = {
            enable = mkOption { 
              type = types.bool; 
              default = false;
              description = "Enable beesd deduplication for this filesystem";
            };
            hashTableSizeMB = mkOption { 
              type = types.int; 
              default = 1024;
              description = "Hash table size in MB (should be multiple of 16)";
            };
            verbosity = mkOption { 
              type = types.str; 
              default = "info";
              description = "Logging verbosity level";
            };
          };
          balance = {
            enable = mkOption { 
              type = types.bool; 
              default = false;
              description = "Enable periodic balance operations";
            };
            interval = mkOption { 
              type = types.str; 
              default = "monthly";
              description = "Balance interval (systemd timer format)";
            };
            dataUsage = mkOption { 
              type = types.int; 
              default = 50;
              description = "Data usage threshold for balance";
            };
            metadataUsage = mkOption { 
              type = types.int; 
              default = 50;
              description = "Metadata usage threshold for balance";
            };
          };
          
          # Mountpoint-based configuration
          mountpoints = mkOption {
            type = types.attrsOf (types.submodule {
              options = {
                subvolume = mkOption { 
                  type = types.nullOr types.str; 
                  default = null;
                  description = "Subvolume name. If null, uses default subvolume.";
                };
                compression = mkOption { 
                  type = types.str; 
                  default = "zstd";
                  description = "Compression algorithm (zstd, lzo, lz4, none)";
                };
                autodefrag = mkOption { 
                  type = types.bool; 
                  default = false;
                  description = "Enable automatic defragmentation";
                };
                extraOptions = mkOption { 
                  type = types.listOf types.str; 
                  default = [];
                  description = "Additional mount options";
                };
              };
            });
            default = {};
            description = "Mountpoint configurations for this filesystem";
          };
        };
      });
      default = {};
      description = "Btrfs filesystems configuration";
    };
  };

  config = mkIf cfg.enable {
    environment.systemPackages = with pkgs; [
      btrfs-progs
      compsize
    ];

    # Generate fileSystems configuration from mountpoints
    fileSystems = mkMerge (flatten (mapAttrsToList (device: fsCfg:
      mapAttrsToList (mountpoint: mountCfg:
        {
          ${mountpoint} = {
            device = device;
            fsType = "btrfs";
            options = 
              (optional (mountCfg.subvolume != null) "subvol=${mountCfg.subvolume}") ++
              [ "compress=${mountCfg.compression}" ] ++
              (optional mountCfg.autodefrag "autodefrag") ++
              mountCfg.extraOptions;
          };
        }
      ) fsCfg.mountpoints
    ) cfg.filesystems));
    
    # Configure scrub service using NixOS built-in
    services.btrfs.autoScrub = mkIf (any (fs: fs.scrub.enable) (attrValues cfg.filesystems)) {
      enable = true;
      interval = "weekly"; # TODO: Make this configurable per filesystem
      fileSystems = attrNames (filterAttrs (_: fs: fs.scrub.enable) cfg.filesystems);
    };
    
    # Configure beesd for filesystems with deduplication enabled
    services.beesd.filesystems = mapAttrs' (device: fsCfg: 
      nameValuePair (replaceStrings ["/"] ["_"] (replaceStrings ["-"] ["_"] device)) {
        spec = device;
        hashTableSizeMB = fsCfg.deduplication.hashTableSizeMB;
        verbosity = fsCfg.deduplication.verbosity;
      }
    ) (filterAttrs (_: fs: fs.deduplication.enable) cfg.filesystems);
    
    # Custom balance services for filesystems with balance enabled
    systemd.services = mkMerge (mapAttrsToList (device: fsCfg: mkIf fsCfg.balance.enable {
      "btrfs-balance-${replaceStrings ["/"] ["-"] (replaceStrings ["-"] ["_"] device)}" = {
        description = "Balance btrfs filesystem ${device}";
        script = ''
          ${pkgs.btrfs-progs}/bin/btrfs balance start \
            -dusage=${toString fsCfg.balance.dataUsage} \
            -musage=${toString fsCfg.balance.metadataUsage} \
            ${device}
        '';
        serviceConfig = {
          Type = "oneshot";
          Nice = 19;
          IOSchedulingClass = "idle";
        };
      };
    }) cfg.filesystems);
    
    # Balance timers
    systemd.timers = mkMerge (mapAttrsToList (device: fsCfg: mkIf fsCfg.balance.enable {
      "btrfs-balance-${replaceStrings ["/"] ["-"] (replaceStrings ["-"] ["_"] device)}" = {
        description = "Periodic balance for ${device}";
        wantedBy = [ "timers.target" ];
        timerConfig = {
          OnCalendar = fsCfg.balance.interval;
          Persistent = true;
        };
      };
    }) cfg.filesystems);
  };
}
