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

with lib;

let
  cfg = config.roles.remote-build;
in
{
  options.roles.remote-build = {
    enableBuilder = mkOption {
      type = types.bool;
      default = false;
      description = "Enable this machine as a remote build host for other machines";
    };

    builderUser = mkOption {
      type = types.str;
      default = "nix-builder";
      description = "User account for remote builders to connect as";
    };

    builders = mkOption {
      type = types.listOf (types.submodule {
        options = {
          hostName = mkOption {
            type = types.str;
            description = "Hostname or IP address of the build machine";
          };

          systems = mkOption {
            type = types.listOf types.str;
            default = [ "x86_64-linux" ];
            description = "Supported systems";
          };

          maxJobs = mkOption {
            type = types.int;
            default = 8;
            description = "Maximum number of parallel build jobs";
          };

          speedFactor = mkOption {
            type = types.int;
            default = 2;
            description = "Speed factor compared to local building (higher = prefer remote)";
          };

          supportedFeatures = mkOption {
            type = types.listOf types.str;
            default = [ "nixos-test" "benchmark" "big-parallel" "kvm" ];
            description = "Supported build features";
          };

          sshUser = mkOption {
            type = types.str;
            default = "nix-builder";
            description = "SSH user for connecting to the builder";
          };

          sshKey = mkOption {
            type = types.nullOr types.path;
            default = null;
            description = "Path to SSH private key for authentication";
          };
        };
      });
      default = [];
      description = "List of remote build machines to use";
    };

    fallbackToLocalBuild = mkOption {
      type = types.bool;
      default = true;
      description = "Fallback to local building if remote builders are unavailable";
    };
  };

  config = mkMerge [
    # Builder host configuration
    (mkIf cfg.enableBuilder {
      # Create dedicated builder user
      users.users.${cfg.builderUser} = {
        isSystemUser = true;
        group = cfg.builderUser;
        description = "Nix remote build user";
        home = "/var/lib/${cfg.builderUser}";
        createHome = true;
        shell = pkgs.bashInteractive;
        openssh.authorizedKeys.keyFiles = [];  # Will be populated by client machines
      };

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

      # Ensure home directory has correct permissions
      systemd.tmpfiles.rules = [
        "d /var/lib/${cfg.builderUser} 0700 ${cfg.builderUser} ${cfg.builderUser} -"
      ];

      # Allow builder user to perform builds
      nix.settings.trusted-users = [ cfg.builderUser ];

      # Allow remote builds
      services.openssh.enable = true;

      # Ensure nix-daemon is accessible
      nix.settings.allowed-users = [ "*" ];
    })

    # Client configuration (machines using remote builders)
    (mkIf (cfg.builders != []) {
      nix.buildMachines = map (builder: {
        hostName = builder.hostName;
        systems = builder.systems;
        maxJobs = builder.maxJobs;
        speedFactor = builder.speedFactor;
        supportedFeatures = builder.supportedFeatures;
        sshUser = builder.sshUser;
        sshKey = builder.sshKey;
      }) cfg.builders;

      nix.distributedBuilds = true;

      # Use substitutes from remote builders
      nix.extraOptions = ''
        builders-use-substitutes = true
      '';

      # Fallback to local build if remote unavailable
      nix.settings.fallback = cfg.fallbackToLocalBuild;
    })
  ];
}
