import { readFileSync } from "node:fs";

import type { AgentRunLaneSecretSpec, AgentRunLaneSpec } from "../agentrun-lanes";
import type { UniDeskConfig } from "../config";
import { rootPath } from "../config";
import { sha256Fingerprint } from "../platform-infra-ops-library";

import { capture, captureJsonPayload, compactCapture, record, shQuote } from "./utils";

export const AGENTRUN_MANAGER_RETENTION_ISSUE = "https://github.com/pikasTech/agentrun/issues/280";
export const AGENTRUN_MANAGER_RETENTION_PULL_REQUEST = "https://github.com/pikasTech/agentrun/pull/281";
export const AGENTRUN_MANAGER_RECONCILER_ISSUE = "https://github.com/pikasTech/agentrun/issues/282";
export const AGENTRUN_PROVIDER_ACTIVATION_FENCE_ISSUE = "https://github.com/pikasTech/agentrun/issues/284";

export interface ProviderSecretActivationTarget {
  readonly id: string;
  readonly targetRef: AgentRunLaneSecretSpec["targetRef"];
  readonly desiredEncodedFingerprint: string;
}

export function providerSecretDesiredEncodedFingerprint(value: string): string {
  return sha256Fingerprint(Buffer.from(value, "utf8").toString("base64"));
}

export function providerSecretActivationPreflightScript(spec: AgentRunLaneSpec, targets: readonly ProviderSecretActivationTarget[]): string {
  const script = readFileSync(rootPath("scripts/src/agentrun/provider-secret-activation-preflight.mjs"), "utf8");
  return [
    "set -eu",
    `namespace=${shQuote(spec.runtime.namespace)}`,
    `targets_json_b64=${shQuote(Buffer.from(JSON.stringify(targets), "utf8").toString("base64"))}`,
    `match_labels_json_b64=${shQuote(Buffer.from(JSON.stringify(spec.deployment.runner.retention.selectors.matchLabels), "utf8").toString("base64"))}`,
    `job_name_prefixes_json_b64=${shQuote(Buffer.from(JSON.stringify(spec.deployment.runner.retention.selectors.jobNamePrefixes), "utf8").toString("base64"))}`,
    "tmp_dir=$(mktemp -d)",
    "trap 'rm -rf \"$tmp_dir\"' EXIT",
    "cat > \"$tmp_dir/provider-secret-activation-preflight.mjs\" <<'NODE'",
    script,
    "NODE",
    "env NAMESPACE=\"$namespace\" TARGETS_JSON_B64=\"$targets_json_b64\" MATCH_LABELS_JSON_B64=\"$match_labels_json_b64\" JOB_NAME_PREFIXES_JSON_B64=\"$job_name_prefixes_json_b64\" node \"$tmp_dir/provider-secret-activation-preflight.mjs\"",
  ].join("\n");
}

export async function providerSecretActivationPreflight(
  config: UniDeskConfig,
  spec: AgentRunLaneSpec,
  targets: readonly ProviderSecretActivationTarget[],
  options: { readonly full?: boolean } = {},
): Promise<Record<string, unknown> & { ok: boolean }> {
  const result = await capture(config, spec.nodeKubeRoute, ["sh", "--", providerSecretActivationPreflightScript(spec, targets)]);
  const payload = captureJsonPayload(result);
  const ok = result.exitCode === 0
    && payload.ok === true
    && payload.targetSecretObservationComplete === true
    && payload.providerSecretDataNoOp === true
    && Number(payload.providerSecretMutationCount ?? -1) === 0;
  const visiblePayload = options.full === true ? payload : compactProviderSecretActivationPayload(payload);
  return {
    ...visiblePayload,
    ok,
    status: ok ? "ready" : "blocked",
    reason: ok ? null : payload.reason ?? (result.exitCode === 0 ? "provider-secret-activation-preflight-blocked" : "provider-secret-activation-preflight-failed"),
    capture: compactCapture(result, {
      full: options.full === true || result.exitCode !== 0,
      stdoutTailChars: 2400,
      stderrTailChars: 2400,
    }),
    managerAuthority: {
      owner: "agentrun-manager-provider-activation-fence",
      requiredBeforeActivation: record(payload).requiresManagerFence === true,
      atomicFenceAvailable: false,
      mutationAuthorized: false,
      noOpOnly: true,
      trackingIssue: AGENTRUN_PROVIDER_ACTIVATION_FENCE_ISSUE,
      retentionDependencies: {
        issue: AGENTRUN_MANAGER_RETENTION_ISSUE,
        pullRequest: AGENTRUN_MANAGER_RETENTION_PULL_REQUEST,
        stalePendingReconcilerIssue: AGENTRUN_MANAGER_RECONCILER_ISSUE,
        sufficientForProviderActivation: false,
        valuesPrinted: false,
      },
      valuesPrinted: false,
    },
    mutation: false,
    runtimeSecretValuesDecoded: false,
    valuesPrinted: false,
  };
}

function compactProviderSecretActivationPayload(payload: Record<string, unknown>): Record<string, unknown> {
  const targetSecrets = Array.isArray(payload.targetSecrets) ? payload.targetSecrets.map(record) : [];
  const risks = Array.isArray(payload.activationRisks) ? payload.activationRisks.map(record) : [];
  const visibleRisks = risks.slice(0, 1).map((risk) => ({
    pod: risk.pod ?? null,
    jobName: risk.jobName ?? null,
    phase: risk.phase ?? null,
    createdAt: risk.createdAt ?? null,
    runId: risk.runId ?? null,
    commandId: risk.commandId ?? null,
    runnerJobId: risk.runnerJobId ?? null,
    runnerId: risk.runnerId ?? null,
    waitingReasons: Array.isArray(risk.waitingReasons) ? risk.waitingReasons.slice(0, 4) : [],
    dependencies: Array.isArray(risk.dependencies)
      ? risk.dependencies.map(record).slice(0, 2).map((dependency) => ({
        source: dependency.source ?? null,
        name: dependency.name ?? null,
        affectedDesiredKeys: Array.isArray(dependency.affectedDesiredKeys) ? dependency.affectedDesiredKeys.slice(0, 8) : [],
        mutationKinds: Array.isArray(dependency.mutationKinds) ? dependency.mutationKinds.slice(0, 4) : [],
        reason: dependency.reason ?? null,
        valuesPrinted: false,
      }))
      : [],
    classification: risk.classification ?? null,
    valuesPrinted: false,
  }));
  return {
    ok: payload.ok === true,
    status: payload.status ?? null,
    reason: payload.reason ?? null,
    observedAt: payload.observedAt ?? null,
    target: payload.target ?? null,
    targetSecretCount: payload.targetSecretCount ?? targetSecrets.length,
    targetSecrets: targetSecrets.map((target) => ({
      namespace: target.namespace ?? null,
      name: target.name ?? null,
      desiredKeys: Array.isArray(target.desiredKeys) ? target.desiredKeys.slice(0, 8) : [],
      queryOk: target.queryOk === true,
      present: typeof target.present === "boolean" ? target.present : null,
      mutationCount: target.mutationCount ?? null,
      noOp: target.noOp === true,
      mutations: Array.isArray(target.mutations)
        ? target.mutations.map(record).slice(0, 8).map((mutation) => ({
          id: mutation.id ?? null,
          key: mutation.key ?? null,
          desiredFingerprintSuffix: typeof mutation.desiredEncodedFingerprint === "string" ? mutation.desiredEncodedFingerprint.slice(-12) : null,
          runtimeFingerprintSuffix: typeof mutation.runtimeEncodedFingerprint === "string" ? mutation.runtimeEncodedFingerprint.slice(-12) : null,
          changeKind: mutation.changeKind ?? null,
          valuesPrinted: false,
        }))
        : [],
      valuesPrinted: false,
    })),
    podObservation: payload.podObservation ?? null,
    targetSecretObservationComplete: payload.targetSecretObservationComplete === true,
    runnerObservationComplete: payload.runnerObservationComplete === true,
    allObservationsComplete: payload.allObservationsComplete === true,
    providerSecretMutationCount: payload.providerSecretMutationCount ?? null,
    providerSecretDataNoOp: payload.providerSecretDataNoOp === true,
    providerSecretMutationAuthorized: payload.providerSecretMutationAuthorized === true,
    activationAuthority: payload.activationAuthority ?? null,
    activationRiskCount: payload.activationRiskCount ?? risks.length,
    activationRisks: visibleRisks,
    activationRiskOmittedCount: Math.max(0, Number(payload.activationRiskCount ?? risks.length) - visibleRisks.length),
    requiresManagerFence: payload.requiresManagerFence === true,
    queryComplete: payload.queryComplete === true,
    mutation: false,
    runtimeSecretValuesDecoded: false,
    valuesPrinted: false,
  };
}

export function providerSecretStagedActivation(
  spec: AgentRunLaneSpec,
  profiles: readonly string[],
): Record<string, unknown> {
  return {
    status: "blocked-before-secret-activation",
    targetProfiles: [...new Set(profiles)],
    secretMutationStarted: false,
    requiredSequence: [
      "agentrun-manager-reconcile-terminalize-and-fence-affected-runners",
      "agentrun-manager-acquire-provider-activation-admission-fence-and-secret-cas",
      "repeat-provider-secret-activation-preflight",
      "sync-yaml-declared-provider-secret",
    ],
    managerTrackingIssue: AGENTRUN_MANAGER_RETENTION_ISSUE,
    managerTrackingPullRequest: AGENTRUN_MANAGER_RETENTION_PULL_REQUEST,
    managerReconcilerIssue: AGENTRUN_MANAGER_RECONCILER_ISSUE,
    providerActivationFenceIssue: AGENTRUN_PROVIDER_ACTIVATION_FENCE_ISSUE,
    retry: `bun scripts/cli.ts agentrun provider-profile apply --node ${spec.nodeId} --lane ${spec.lane} --profile <profile> --confirm`,
    valuesPrinted: false,
  };
}
