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

let
  cfg = config.ultracloud.quickstart;

  localChainfire = "127.0.0.1:${toString config.services.chainfire.port}";
  localChainfireHttp = "http://127.0.0.1:${toString config.services.chainfire.httpPort}";
  localFlaredb = "127.0.0.1:${toString config.services.flaredb.port}";
  localIamGrpc = "127.0.0.1:${toString config.services.iam.port}";
  localIamHttp = "http://127.0.0.1:${toString config.services.iam.httpPort}";
  localPrismnetGrpc = "127.0.0.1:${toString config.services.prismnet.port}";
  localPrismnetHttp = "http://127.0.0.1:${toString config.services.prismnet.httpPort}";
  localPlasmavmcHttp = "http://127.0.0.1:${toString config.services.plasmavmc.httpPort}";
  localLightningstorGrpc = "127.0.0.1:${toString config.services.lightningstor.port}";
  localCreditserviceGrpc = "127.0.0.1:${toString config.services.creditservice.grpcPort}";
  localFiberlbHttp = "http://127.0.0.1:${toString config.services.fiberlb.port}";
  localFlashdnsHttp = "http://127.0.0.1:${toString config.services.flashdns.port}";
  localCoronafsHttp = "http://127.0.0.1:${toString config.services.coronafs.port}";

  requiredPackages = with pkgs; [
    chainfire-server
    flaredb-server
    iam-server
    prismnet-server
    plasmavmc-server
    curl
    iproute2
    jq
    qemu
  ];

  optionalPackages =
    (lib.optionals cfg.enableLightningStor [ pkgs.lightningstor-server ])
    ++ (lib.optionals cfg.enableCoronafs [ pkgs.coronafs-server ])
    ++ (lib.optionals cfg.enableFlashDNS [ pkgs.flashdns-server ])
    ++ (lib.optionals cfg.enableFiberLB [ pkgs.fiberlb-server ])
    ++ (lib.optionals cfg.enableApiGateway [ pkgs.apigateway-server ])
    ++ (lib.optionals cfg.enableNightlight [ pkgs.nightlight-server ])
    ++ (lib.optionals cfg.enableCreditService [ pkgs.creditservice-server ])
    ++ (lib.optionals cfg.enableK8sHost [ pkgs.k8shost-server ]);

  requiredUnits = [
    "chainfire.service"
    "flaredb.service"
    "iam.service"
    "prismnet.service"
    "plasmavmc.service"
  ];

  optionalUnits =
    (lib.optionals cfg.enableLightningStor [ "lightningstor.service" ])
    ++ (lib.optionals cfg.enableCoronafs [ "coronafs.service" ])
    ++ (lib.optionals cfg.enableFlashDNS [ "flashdns.service" ])
    ++ (lib.optionals cfg.enableFiberLB [ "fiberlb.service" ])
    ++ (lib.optionals cfg.enableApiGateway [ "apigateway.service" ])
    ++ (lib.optionals cfg.enableNightlight [ "nightlight.service" ])
    ++ (lib.optionals cfg.enableCreditService [ "creditservice.service" ])
    ++ (lib.optionals cfg.enableK8sHost [ "k8shost.service" ]);

  readyUnitArgs = lib.escapeShellArgs (requiredUnits ++ optionalUnits);

  healthChecks = [
    { name = "chainfire"; url = "http://127.0.0.1:8081/health"; }
    { name = "flaredb"; url = "http://127.0.0.1:8082/health"; }
    { name = "iam"; url = "http://127.0.0.1:8083/health"; }
    { name = "prismnet"; url = "http://127.0.0.1:8087/health"; }
    { name = "plasmavmc"; url = localPlasmavmcHttp + "/health"; }
  ]
  ++ lib.optionals cfg.enableCoronafs [
    { name = "coronafs"; url = localCoronafsHttp + "/healthz"; }
  ]
  ++ lib.optionals cfg.enableApiGateway [
    { name = "apigateway"; url = "http://127.0.0.1:8080/health"; }
  ]
  ++ lib.optionals cfg.enableNightlight [
    { name = "nightlight"; url = "http://127.0.0.1:9101/healthz"; }
  ]
  ++ lib.optionals cfg.enableCreditService [
    { name = "creditservice"; url = "http://127.0.0.1:3011/health"; }
  ]
  ++ lib.optionals cfg.enableK8sHost [
    { name = "k8shost"; url = "http://127.0.0.1:8085/health"; }
  ];

  healthCheckScript = lib.concatMapStringsSep "\n" (check: ''
    wait_for_health ${lib.escapeShellArg check.name} ${lib.escapeShellArg check.url}
  '') healthChecks;
in
{
  options.ultracloud.quickstart = {
    enable = lib.mkEnableOption "UltraCloud single-node quickstart profile";

    hostName = lib.mkOption {
      type = lib.types.str;
      default = "single-node-quickstart";
      description = "Hostname used by the single-node quickstart profile.";
    };

    nodeId = lib.mkOption {
      type = lib.types.str;
      default = "single01";
      description = "Node identifier for the single-node quickstart profile.";
    };

    enableLightningStor = lib.mkEnableOption "LightningStor object/image storage add-on for the quickstart";
    enableCoronafs = lib.mkEnableOption "CoronaFS shared-volume add-on for the quickstart";
    enableFlashDNS = lib.mkEnableOption "FlashDNS add-on for the quickstart";
    enableFiberLB = lib.mkEnableOption "FiberLB add-on for the quickstart";
    enableApiGateway = lib.mkEnableOption "API gateway add-on for the quickstart";
    enableNightlight = lib.mkEnableOption "Nightlight metrics add-on for the quickstart";
    enableCreditService = lib.mkEnableOption "CreditService reference add-on for the quickstart";
    enableK8sHost = lib.mkEnableOption "K8sHost add-on for the quickstart";
  };

  config = lib.mkIf cfg.enable {
    assertions = [
      {
        assertion = !cfg.enableK8sHost || (cfg.enableFiberLB && cfg.enableFlashDNS);
        message = "ultracloud.quickstart.enableK8sHost requires ultracloud.quickstart.enableFiberLB and ultracloud.quickstart.enableFlashDNS.";
      }
    ];

    networking.hostName = lib.mkDefault cfg.hostName;
    networking.useDHCP = lib.mkDefault true;
    networking.vswitches = lib.mkDefault {};

    networking.firewall.allowedTCPPorts = [
      22
      2379
      2380
      2381
      2479
      2480
      50080
      50081
      50082
      8081
      8082
      8083
      8084
      8087
    ]
    ++ (lib.optionals cfg.enableLightningStor [ 50086 50090 9000 ])
    ++ (lib.optionals cfg.enableCoronafs [ 50088 ])
    ++ (lib.optionals cfg.enableFlashDNS [ 50084 ])
    ++ (lib.optionals cfg.enableFiberLB [ 50085 ])
    ++ (lib.optionals cfg.enableApiGateway [ 8080 ])
    ++ (lib.optionals cfg.enableNightlight [ 9091 9101 ])
    ++ (lib.optionals cfg.enableCreditService [ 3010 3011 ])
    ++ (lib.optionals cfg.enableK8sHost [ 50087 8085 ]);

    networking.firewall.allowedUDPPorts =
      [ 2381 4789 ]
      ++ (lib.optionals cfg.enableFlashDNS [ 5353 ]);

    boot.kernelModules = [ "kvm-intel" "kvm-amd" "tun" ];
    boot.extraModprobeConfig = ''
      options kvm_intel nested=1
      options kvm_amd nested=1
    '';
    boot.kernel.sysctl = {
      "fs.file-max" = 1000000;
      "net.core.netdev_max_backlog" = 5000;
      "net.core.rmem_max" = 134217728;
      "net.core.wmem_max" = 134217728;
      "net.ipv4.ip_forward" = 1;
      "net.ipv6.conf.all.forwarding" = 1;
      "vm.swappiness" = 10;
    };

    services.chainfire = {
      enable = true;
      nodeId = cfg.nodeId;
      initialPeers = [ "${cfg.nodeId}=127.0.0.1:2380" ];
    };

    services.flaredb = {
      enable = true;
      nodeId = cfg.nodeId;
      initialPeers = [ "${cfg.nodeId}=127.0.0.1:2479" ];
      pdAddr = localChainfire;
    };

    services.iam = {
      enable = true;
      chainfireAddr = localChainfire;
      flaredbAddr = localFlaredb;
      allowRandomSigningKey = true;
      allowUnauthenticatedAdmin = true;
    };

    services.prismnet = {
      enable = true;
      iamAddr = localIamGrpc;
      chainfireAddr = localChainfire;
      flaredbAddr = localFlaredb;
    };

    services.plasmavmc = {
      enable = true;
      mode = "all-in-one";
      prismnetAddr = localPrismnetGrpc;
      iamAddr = localIamGrpc;
      chainfireAddr = localChainfire;
      flaredbAddr = localFlaredb;
      lightningstorAddr = if cfg.enableLightningStor then localLightningstorGrpc else null;
      coronafsControllerEndpoint = if cfg.enableCoronafs then localCoronafsHttp else null;
      coronafsNodeEndpoint = if cfg.enableCoronafs then localCoronafsHttp else null;
    };

    services.lightningstor = lib.mkIf cfg.enableLightningStor {
      enable = true;
      mode = "all-in-one";
      objectStorageBackend = "local_fs";
      iamAddr = localIamGrpc;
      chainfireAddr = localChainfire;
      flaredbAddr = localFlaredb;
    };

    services.coronafs = lib.mkIf cfg.enableCoronafs {
      enable = true;
      metadataBackend = "chainfire";
      chainfireApiUrl = localChainfireHttp;
      advertiseHost = "127.0.0.1";
    };

    services.flashdns = lib.mkIf cfg.enableFlashDNS {
      enable = true;
      iamAddr = localIamGrpc;
      chainfireAddr = localChainfire;
      flaredbAddr = localFlaredb;
    };

    services.fiberlb = lib.mkIf cfg.enableFiberLB {
      enable = true;
      iamAddr = localIamGrpc;
      chainfireAddr = localChainfire;
      flaredbAddr = localFlaredb;
    };

    services.creditservice = lib.mkIf cfg.enableCreditService {
      enable = true;
      iamAddr = localIamGrpc;
      chainfireAddr = localChainfire;
      flaredbAddr = localFlaredb;
    };

    services.nightlight = lib.mkIf cfg.enableNightlight {
      enable = true;
    };

    services.apigateway = lib.mkIf cfg.enableApiGateway {
      enable = true;
      authProviders = [
        {
          name = "iam";
          providerType = "grpc";
          endpoint = localIamHttp;
        }
      ];
      creditProviders = lib.optionals cfg.enableCreditService [
        {
          name = "creditservice";
          providerType = "grpc";
          endpoint = "http://${localCreditserviceGrpc}";
        }
      ];
      routes =
        [
          {
            name = "iam-rest";
            pathPrefix = "/iam";
            upstream = localIamHttp;
            stripPrefix = true;
            auth = {
              provider = "iam";
              mode = "required";
            };
          }
        ]
        ++ lib.optionals cfg.enableCreditService [
          {
            name = "credit-rest";
            pathPrefix = "/credit";
            upstream = "http://127.0.0.1:${toString config.services.creditservice.httpPort}";
            stripPrefix = true;
            auth = {
              provider = "iam";
              mode = "required";
            };
            credit = {
              provider = "creditservice";
              mode = "optional";
              units = 1;
              commitOn = "success";
            };
          }
        ];
    };

    services.k8shost = lib.mkIf cfg.enableK8sHost {
      enable = true;
      iamAddr = localIamHttp;
      chainfireAddr = "http://${localChainfire}";
      prismnetAddr = localPrismnetHttp;
      flaredbPdAddr = localChainfire;
      flaredbDirectAddr = localFlaredb;
      fiberlbAddr = localFiberlbHttp;
      flashdnsAddr = localFlashdnsHttp;
      creditserviceAddr =
        if cfg.enableCreditService
        then "http://${localCreditserviceGrpc}"
        else null;
    };

    environment.systemPackages = requiredPackages ++ optionalPackages;

    systemd.services.ultracloud-single-node-quickstart-ready = {
      description = "Verify UltraCloud single-node quickstart readiness";
      wantedBy = [ "multi-user.target" ];
      after = requiredUnits ++ optionalUnits;
      wants = requiredUnits ++ optionalUnits;
      path = [ pkgs.coreutils pkgs.curl pkgs.qemu pkgs.systemd ];
      serviceConfig = {
        Type = "oneshot";
        RemainAfterExit = true;
      };
      script = ''
        set -euo pipefail

        wait_for_health() {
          local name="$1"
          local url="$2"
          local deadline=$((SECONDS + 180))
          while true; do
            if curl -fsS "$url" >/dev/null 2>&1; then
              return 0
            fi
            if [ "$SECONDS" -ge "$deadline" ]; then
              echo "timed out waiting for $name at $url" >&2
              return 1
            fi
            sleep 1
          done
        }

        systemctl is-active ${readyUnitArgs}
        ${healthCheckScript}
        test -x ${pkgs.qemu}/bin/qemu-system-x86_64
        test -x ${pkgs.qemu}/bin/qemu-img
        test -c /dev/net/tun
        if [ -e /dev/kvm ]; then
          test -r /dev/kvm
        fi
      '';
    };

    system.stateVersion = "24.11";
  };
}
