{
  config,
  lib,
  nodes,
  ...
}:
with lib; let
  cfg = config.homelab.backups;
  homelabCfg = config.homelab;
  hasNodes = length (attrNames nodes) > 0;

  # Get all defined backend names dynamically
  backendNames = attrNames cfg.backends or {};

  backupJobType = types.submodule {
    options = {
      name = mkOption {
        type = types.str;
        description = "Name of the backup job";
      };
      backend = mkOption {
        type = types.enum backendNames;
        description = "Backend to use for this backup job";
      };
      backendOptions = mkOption {
        type = types.attrs;
        default = {};
        description = "Backend-specific options to override or extend the backend configuration";
      };
      labels = mkOption {
        type = types.attrsOf types.str;
        default = {};
        description = "Additional labels for this backup job";
      };
    };
  };

  # Local aggregation
  localAggregation = {
    allJobs = cfg.jobs;
    allBackends = backendNames;
  };

  # Global aggregation
  globalAggregation = let
    baseAgg = import ../aggregators/base.nix {inherit lib;};

    jobsAgg = baseAgg.aggregateFromNodes {
      inherit nodes;
      attributePath = "homelab.backups.allJobs";
      enhancer = job:
        job
        // {
          _sourceNode = job._nodeName;
          _backupId = "${job._nodeName}-${job.name}";
          _jobFqdn = "${job.name}.${job._nodeName}";
        };
    };

    # Get all backends from all nodes
    allBackendsFromNodes = let
      backendConfigs =
        mapAttrsToList (
          nodeName: nodeConfig:
            attrByPath ["homelab" "backups" "backends"] {} nodeConfig.config
        )
        nodes;
      enabledBackends = flatten (map (
          backends:
            filter (name: backends.${name} != null) (attrNames backends)
        )
        backendConfigs);
    in
      unique enabledBackends;
  in {
    allJobs = jobsAgg.all;
    allBackends = allBackendsFromNodes;
    jobsByBackend = groupBy (j: j.backend) jobsAgg.all;
    summary = {
      total = length jobsAgg.all;
      byBackend = jobsAgg.countBy (j: j.backend);
      byNode = jobsAgg.countBy (j: j._nodeName);
      uniqueBackends = unique (map (j: j.backend) jobsAgg.all);
    };
  };
in {
  imports = [
    ../../backup/restic.nix
    # ./backup/borgbackup.nix
  ];

  options.homelab.backups = {
    enable = mkEnableOption "backup system";

    jobs = mkOption {
      type = types.listOf backupJobType;
      default = [];
      description = "Backup jobs to execute on this system";
    };

    # Backend configurations (like your existing setup)
    # backends = mkOption {
    #   type = types.attrs;
    #   default = {};
    #   description = "Backup backend configurations";
    # };

    defaultLabels = mkOption {
      type = types.attrsOf types.str;
      default = {
        hostname = homelabCfg.hostname;
        environment = homelabCfg.environment;
        location = homelabCfg.location;
      };
      description = "Default labels applied to all backup jobs";
    };

    monitoring = mkOption {
      type = types.bool;
      default = true;
      description = "Enable backup monitoring and metrics";
    };

    # Always exposed aggregated data
    allJobs = mkOption {
      type = types.listOf types.attrs;
      default = localAggregation.allJobs;
      readOnly = true;
    };

    allBackends = mkOption {
      type = types.listOf types.str;
      default = localAggregation.allBackends;
      readOnly = true;
    };

    global = mkOption {
      type = types.attrs;
      default = globalAggregation;
      readOnly = true;
    };
  };

  config = mkIf cfg.enable {
    # Validate that all job backends exist
    assertions = [
      {
        assertion = all (job: cfg.backends.${job.backend} != null) cfg.jobs;
        message = "All backup jobs must reference backends that are defined and not null in homelab.backups.backends";
      }
    ];

    # Always expose both local and global
    # homelab.backups = {
    #   allJobs = localAggregation.allJobs;
    #   allBackends = localAggregation.allBackends;
    #   global =
    #     if hasNodes
    #     then globalAggregation
    #     else {};
    # };
  };
}
