import { readFileSync } from "node:fs";
import { codeQueueContainerdImagePreflight, codeQueueManifestImagePreflight } from "./src/deploy";

type JsonRecord = Record<string, unknown>;

function assertCondition(condition: unknown, message: string, detail: JsonRecord = {}): void {
  if (!condition) throw new Error(`${message}: ${JSON.stringify(detail)}`);
}

function gatewayCheck(diagnostics: JsonRecord): JsonRecord {
  const checks = diagnostics.checks as JsonRecord | undefined;
  const deployment = checks?.deployment as JsonRecord | undefined;
  const endpoint = checks?.endpoint as JsonRecord | undefined;
  const target = checks?.targetService as JsonRecord | undefined;
  const deploymentAvailable = deployment?.available === true;
  const endpointNonEmpty = Number(endpoint?.readyAddressCount ?? 0) > 0;
  return {
    ok: diagnostics.ok === true && deploymentAvailable && endpointNonEmpty && target?.ok === true,
    deploymentAvailable,
    endpointNonEmpty,
    targetServiceOk: target?.ok === true,
  };
}

function schedulerStorageCheck(schedulerHealth: JsonRecord): JsonRecord {
  const queue = schedulerHealth.queue as JsonRecord | undefined;
  const storage = queue?.storage as JsonRecord | undefined;
  const lastError = storage?.lastError ?? null;
  return {
    ok: storage?.postgresReady === true && lastError === null,
    postgresReady: storage?.postgresReady === true,
    lastError,
  };
}

function staleReconcileCheck(schedulerHealth: JsonRecord): JsonRecord {
  const queue = schedulerHealth.queue as JsonRecord | undefined;
  const reconcile = queue?.reconcile as JsonRecord | undefined;
  const recoverable = Number(reconcile?.recoverableOrphanedActiveTaskCount ?? queue?.orphanedActiveTaskCount ?? 0);
  return {
    ok: recoverable === 0,
    recoverableOrphanedActiveTaskCount: recoverable,
    retryWaitTaskCount: Number(reconcile?.retryWaitTaskCount ?? 0),
  };
}

function runIssue3Regression(): JsonRecord {
  const missingEndpointGateway = gatewayCheck({
    ok: false,
    checks: {
      deployment: { ok: true, available: true, availableReplicas: 1 },
      endpoint: { ok: false, readyAddressCount: 0 },
      targetService: { ok: false },
    },
  });
  assertCondition(missingEndpointGateway.ok === false, "microservice:code-queue-egress-gateway-health must fail on empty endpoint", missingEndpointGateway);
  assertCondition(missingEndpointGateway.deploymentAvailable === true, "gateway deployment availability should be reported separately", missingEndpointGateway);
  assertCondition(missingEndpointGateway.endpointNonEmpty === false, "gateway endpoint non-empty check should be explicit", missingEndpointGateway);

  const storageFailure = schedulerStorageCheck({
    queue: {
      storage: {
        postgresReady: false,
        lastError: "CONNECT_TIMEOUT d601-tcp-egress-gateway.unidesk.svc.cluster.local:15432",
      },
    },
  });
  assertCondition(storageFailure.ok === false, "diagnostics must fail when scheduler storage.lastError reports PostgreSQL route failure", storageFailure);
  assertCondition(String(storageFailure.lastError).includes("CONNECT_TIMEOUT"), "storage failure detail should preserve route error", storageFailure);

  const staleReconcile = staleReconcileCheck({
    queue: {
      orphanedActiveTaskCount: 1,
      reconcile: {
        recoverableOrphanedActiveTaskCount: 1,
        retryWaitTaskCount: 2,
      },
    },
  });
  assertCondition(staleReconcile.ok === false, "code-queue:stale-active-reconcile must fail while recoverable active tasks remain", staleReconcile);
  assertCondition(staleReconcile.retryWaitTaskCount === 2, "retry_wait reconcile count should be visible", staleReconcile);

  const missingImage = codeQueueContainerdImagePreflight("docker.io/library/busybox:latest\n", "unidesk-code-queue:d601");
  assertCondition(missingImage.ok === false, "code-queue:containerd-image-preflight must fail when k3s containerd lacks unidesk-code-queue:d601", missingImage);
  const presentImage = codeQueueContainerdImagePreflight("docker.io/library/busybox:latest\nunidesk-code-queue:d601 application/vnd.oci.image.manifest.v1+json\n", "unidesk-code-queue:d601");
  assertCondition(presentImage.ok === true, "code-queue:containerd-image-preflight should pass when the tag is present", presentImage);

  const manifestPath = "src/components/microservices/k3sctl-adapter/k3s/code-queue.k8s.yaml";
  const manifest = readFileSync(manifestPath, "utf8");
  const manifestImage = codeQueueManifestImagePreflight(manifest, "unidesk-code-queue:d601");
  assertCondition(manifestImage.ok === true, "Code Queue k8s manifest deployments must all use unidesk-code-queue:d601", manifestImage);

  return {
    ok: true,
    checks: [
      { name: "microservice:code-queue-egress-gateway-health", ok: true },
      { name: "microservice:code-queue-postgres-route-health", ok: true },
      { name: "code-queue:containerd-image-preflight", ok: true },
      { name: "code-queue:stale-active-reconcile", ok: true },
    ],
  };
}

if (import.meta.main) {
  process.stdout.write(`${JSON.stringify(runIssue3Regression(), null, 2)}\n`);
}
