{ lib }:

let
  inherit (lib) concatStringsSep genAttrs mkIf;

  clusterName = "ultracloud-vm-cluster";
  clusterId = clusterName;
  environment = "dev";
  bgpAsn = 64512;

  bootstrapToken = "vm-cluster-bootstrap-token";
  adminToken = "vm-cluster-admin-token";

  chainfireApiPort = 2379;
  chainfireRaftPort = 2380;
  flaredbApiPort = 2479;
  flaredbRaftPort = 2480;
  iamPort = 50080;

  controlPlaneLabels = {
    tier = "control-plane";
    platform = "vm-cluster";
  };

  controlPlaneNodes = {
    node01 = {
      ip = "192.168.100.11";
      failureDomain = "rack-a";
    };
    node02 = {
      ip = "192.168.100.12";
      failureDomain = "rack-b";
    };
    node03 = {
      ip = "192.168.100.13";
      failureDomain = "rack-c";
    };
  };

  controlPlaneNodeNames = builtins.attrNames controlPlaneNodes;
  bootstrapNodeName = builtins.head controlPlaneNodeNames;

  mkEndpoint = nodeName: port:
    let
      node = controlPlaneNodes.${nodeName};
    in
    "${node.ip}:${toString port}";

  chainfireInitialPeers =
    map (nodeName: "${nodeName}=${mkEndpoint nodeName chainfireRaftPort}") controlPlaneNodeNames;

  flaredbInitialPeers =
    map (nodeName: "${nodeName}=${mkEndpoint nodeName flaredbRaftPort}") controlPlaneNodeNames;

  chainfireControlPlaneAddrs =
    concatStringsSep "," (map (nodeName: mkEndpoint nodeName chainfireApiPort) controlPlaneNodeNames);

  flaredbControlPlaneAddrs =
    concatStringsSep "," (map (nodeName: mkEndpoint nodeName flaredbApiPort) controlPlaneNodeNames);

  sharedDesiredSystem = {
    healthCheckCommand = [ "systemctl" "is-system-running" "--wait" ];
    rollbackOnFailure = true;
  };

  mkInstallPlan = nodeName: {
    nixosConfiguration = nodeName;
    diskoConfigPath = "nix/nodes/vm-cluster/${nodeName}/disko.nix";
    targetDisk = "/dev/vda";
  };

  mkClusterNode = nodeName:
    let
      node = controlPlaneNodes.${nodeName};
    in
    {
      role = "control-plane";
      ip = node.ip;
      services = [ "chainfire" "flaredb" "iam" ];
      labels = controlPlaneLabels;
      pool = "control";
      nodeClass = "control-plane";
      failureDomain = node.failureDomain;
      nixProfile = "profiles/control-plane";
      installPlan = mkInstallPlan nodeName;
      desiredSystem = sharedDesiredSystem;
      raftPort = chainfireRaftPort;
      apiPort = chainfireApiPort;
    };

  clusterNodes = genAttrs controlPlaneNodeNames mkClusterNode;

  nodeConfigurationPaths = {
    node01 = ./node01/configuration.nix;
    node02 = ./node02/configuration.nix;
    node03 = ./node03/configuration.nix;
  };

  nodeDiskoPaths = {
    node01 = ./node01/disko.nix;
    node02 = ./node02/disko.nix;
    node03 = ./node03/disko.nix;
  };
in
{
  inherit
    adminToken
    bgpAsn
    bootstrapNodeName
    bootstrapToken
    chainfireApiPort
    chainfireControlPlaneAddrs
    chainfireInitialPeers
    chainfireRaftPort
    clusterId
    clusterName
    clusterNodes
    controlPlaneLabels
    controlPlaneNodeNames
    controlPlaneNodes
    environment
    flaredbApiPort
    flaredbControlPlaneAddrs
    flaredbInitialPeers
    flaredbRaftPort
    iamPort
    nodeConfigurationPaths
    nodeDiskoPaths
    sharedDesiredSystem
    ;

  controlPlaneNodeClass = {
    description = "Control-plane VM cluster nodes";
    nixProfile = "profiles/control-plane";
    roles = [ "control-plane" ];
    labels = controlPlaneLabels;
  };

  controlPlanePool = {
    description = "VM cluster control-plane pool";
    nodeClass = "control-plane";
    labels = {
      plane = "control";
      cluster = "vm-cluster";
    };
  };

  hostDeployments = {
    control-plane-canary = {
      selector.nodeIds = [ bootstrapNodeName ];
      nixosConfiguration = bootstrapNodeName;
      flakeRef = "github:centra/cloud";
      batchSize = 1;
      maxUnavailable = 1;
      healthCheckCommand = sharedDesiredSystem.healthCheckCommand;
      switchAction = "switch";
      rollbackOnFailure = sharedDesiredSystem.rollbackOnFailure;
    };
  };

  mkControlPlaneNodeModule = nodeName:
    { lib, ... }:
    {
      imports = [
        ./cluster.nix
        nodeDiskoPaths.${nodeName}
      ];

      networking.hostName = nodeName;
      networking.useDHCP = lib.mkDefault true;

      boot.loader.grub = {
        enable = true;
        devices = [ "/dev/vda" ];
        efiSupport = true;
        efiInstallAsRemovable = true;
      };

      services.chainfire = {
        enable = true;
        nodeId = nodeName;
        apiAddr = mkEndpoint nodeName chainfireApiPort;
        raftAddr = mkEndpoint nodeName chainfireRaftPort;
        initialPeers = chainfireInitialPeers;
      };

      services.flaredb = {
        enable = true;
        nodeId = nodeName;
        apiAddr = mkEndpoint nodeName flaredbApiPort;
        raftAddr = mkEndpoint nodeName flaredbRaftPort;
        initialPeers = flaredbInitialPeers;
      };

      services.iam = {
        enable = true;
        port = iamPort;
        chainfireAddr = chainfireControlPlaneAddrs;
        flaredbAddr = flaredbControlPlaneAddrs;
      };

      services.openssh.enable = true;
      users.users.root.openssh.authorizedKeys.keys = [ ];

      system.stateVersion = "24.05";
    };

  mkBootstrapServicesModule =
    { self
    , nodeName
    , enableDeployer ? false
    ,
    }:
    { pkgs, lib, ... }:
    {
      services.nix-agent = {
        enable = true;
        chainfireEndpoint = "http://${mkEndpoint bootstrapNodeName chainfireApiPort}";
        clusterId = clusterId;
        nodeId = nodeName;
        flakeRoot = self.outPath;
        intervalSecs = 30;
        apply = true;
      };

      services.deployer = mkIf enableDeployer {
        enable = true;
        bindAddr = "0.0.0.0:8088";
        chainfireEndpoints = [ "http://${mkEndpoint bootstrapNodeName chainfireApiPort}" ];
        clusterId = clusterId;
        requireChainfire = true;
        allowUnknownNodes = false;
        allowUnauthenticated = false;
        bootstrapToken = bootstrapToken;
        adminToken = adminToken;
        bootstrapFlakeBundle = pkgs.ultracloudFlakeBundle;
        seedClusterState = true;
      };
    };
}
