import type { UniDeskConfig } from "../config";
import type { RenderedCliResult } from "../output";
import { desiredAccountNames } from "./accounts";
import { readCodexPoolConfig } from "./config";
import { isRecord } from "./config-utils";
import { protectedManualAccountsForTarget } from "./public-exposure";
import { renderSub2ApiTempUnschedulableCredentials } from "./redaction";
import { boolField, compactCapture, parseJsonOutput, runRemoteCodexPoolScript } from "./remote";
import { compactRuntimeErrors, renderRuntimeResult } from "./runtime-render";
import { runtimeScript } from "./runtime-remote-script";
import { parseRuntimeOptions, type RuntimeOptions } from "./runtime-options";
import { renderRuntimeMutationResult } from "./runtime-mutation-render";
import { codexPoolRuntimeTarget } from "./runtime-target";
export async function codexPoolRuntime(config: UniDeskConfig, args: string[]): Promise<Record<string, unknown> | RenderedCliResult> {
  if (args.includes("--help") || args.includes("-h") || args[0] === "help") return renderRuntimeHelp(args);
  const options = parseRuntimeOptions(args);
  const pool = readCodexPoolConfig();
  const target = codexPoolRuntimeTarget(options.targetId);
  const selectedTemplate = options.kind !== "temp-unschedulable" || options.template === null ? null : pool.runtime.templatesById[options.template];
  if (options.template !== null && selectedTemplate === undefined) {
    throw new Error(`unknown runtime template ${options.template}; available: ${pool.runtime.templates.map((item) => item.id).join(", ")}`);
  }
  const payload = {
    action: options.action,
    account: options.account,
    accounts: options.accounts,
    selectConfiguredPolicy: options.selectConfiguredPolicy,
    accountType: options.accountType,
    excludeAccounts: options.excludeAccounts,
    group: options.group,
    allGroups: options.allGroups,
    platform: options.platform,
    pageToken: options.pageToken,
    kind: options.kind,
    priority: options.priority,
    capacity: options.capacity,
    name: options.name,
    confirm: options.confirm,
    full: options.full,
    recent: options.recent,
    since: options.since,
    tail: options.tail,
    groupName: pool.groupName,
    adminEmailDefault: pool.adminEmailDefault,
    managedAccountNames: desiredAccountNames(pool),
    protectedManualAccountNames: protectedManualAccountsForTarget(pool, target).map((item) => item.accountName),
    templates: pool.runtime.templates.map((template) => ({
      id: template.id,
      kind: template.kind,
      description: template.description,
      credentials: renderSub2ApiTempUnschedulableCredentials(template.tempUnschedulable),
    })),
    selectedTemplate: selectedTemplate === null || selectedTemplate === undefined ? null : {
      id: selectedTemplate.id,
      kind: selectedTemplate.kind,
      credentials: renderSub2ApiTempUnschedulableCredentials(selectedTemplate.tempUnschedulable),
    },
  };
  const result = await runRemoteCodexPoolScript(config, "runtime", runtimeScript(payload, target), target);
  const parsed = parseJsonOutput(result.stdout);
  const ok = result.exitCode === 0 && boolField(parsed, "ok", false);
  if (!options.full && !options.raw && !options.json && (options.action === "apply" || options.action === "delete")) {
    return renderRuntimeMutationResult(ok, options, parsed, result.exitCode);
  }
  if (options.raw) {
    return {
      ok,
      action: "platform-infra-sub2api-codex-pool-runtime",
      remote: compactCapture(result, { full: parsed === null || result.exitCode !== 0 }),
      parsed,
      valuesPrinted: false,
    };
  }
  const response = {
    ok,
    action: "platform-infra-sub2api-codex-pool-runtime",
    target: {
      id: target.id,
      route: target.route,
      namespace: target.namespace,
      runtimeMode: target.runtimeMode,
      endpoint: target.serviceDns,
    },
    request: {
      operation: options.action,
      account: options.account,
      accounts: options.accounts,
      selectConfiguredPolicy: options.selectConfiguredPolicy,
      accountType: options.accountType,
      excludeAccounts: options.excludeAccounts,
      group: options.group,
      allGroups: options.allGroups,
      platform: options.platform,
      pageToken: options.pageToken,
      template: options.template,
      kind: options.kind,
      priority: options.priority,
      capacity: options.capacity,
      name: options.name,
      confirm: options.confirm,
      recent: options.recent,
      since: options.action === "errors" || options.action === "events" || options.action === "infrastructure" ? options.since : undefined,
      tail: options.action === "errors" || options.action === "events" || options.action === "infrastructure" ? options.tail : undefined,
    },
    runtime: options.action === "events"
      ? compactRuntimeEvents(parsed)
      : options.json && (options.action === "apply" || options.action === "delete")
      ? compactRuntimeMutationJson(parsed)
      : compactRuntimeErrors(parsed, options),
    remote: compactCapture(result, { full: result.exitCode !== 0 || parsed === null }),
    disclosure: options.action === "list"
      ? {
        get: "bun scripts/cli.ts platform-infra sub2api codex-pool runtime get --account <name-or-id>",
        errors: "bun scripts/cli.ts platform-infra sub2api codex-pool runtime errors [--account <name-or-id>] [--since 24h]",
      }
      : undefined,
    valuesPrinted: false,
  };
  return options.full || options.json ? response : renderRuntimeResult(response, options);
}

function renderRuntimeHelp(args: string[]): RenderedCliResult {
  const actions = ["list", "get", "errors", "events", "infrastructure", "apply", "delete"] as const;
  const requested = actions.includes(args[0] as typeof actions[number]) ? args[0] as typeof actions[number] : null;
  const command = `platform-infra sub2api codex-pool runtime${requested === null ? "" : ` ${requested}`} --help`;
  const common = [
    "  --target <id>                    YAML-selected Sub2API target",
    "  --json | --full | --raw          Explicit structured or expanded disclosure",
  ];
  const actionHelp: Record<typeof actions[number], string[]> = {
    list: [
      "Usage: bun scripts/cli.ts platform-infra sub2api codex-pool runtime list [--recent <duration>] [--target <id>] [--json|--full|--raw]",
      "",
      "Options:",
      "  --recent <duration>             Show accounts created in the recent m/h/d window",
      ...common,
    ],
    get: [
      "Usage: bun scripts/cli.ts platform-infra sub2api codex-pool runtime get --account <name-or-id> [--target <id>] [--json|--full|--raw]",
      "",
      "Options:",
      "  --account <name-or-id>          Exact account selector",
      ...common,
    ],
    errors: [
      "Usage: bun scripts/cli.ts platform-infra sub2api codex-pool runtime errors [--group <name-or-id>|--all-groups] [--account <name-or-id>] [--platform <name>] [--since <duration>] [--target <id>] [--json|--full|--raw]",
      "",
      "Options:",
      "  --group <name-or-id>            Analyze one group",
      "  --all-groups                    List every group summary; use --page-token to continue",
      "  --account <name-or-id>          Drill into one account after selecting a group",
      "  --platform <name>               Filter by platform",
      "  --page-token <group-id>         Continue --all-groups pagination",
      "  --since <duration>              Analysis window such as 30m, 8h, or 7d",
      "  --tail <count>                  Bounded runtime event tail (100..200000)",
      ...common,
      "",
      "Next: rerun with --group <name-or-id>, then --account <name-or-id> or trace --request-id <id>.",
    ],
    events: [
      "Usage: bun scripts/cli.ts platform-infra sub2api codex-pool runtime events [--since <duration>] [--tail <count>] [--target <id>] [--json|--full|--raw]",
      "",
      "Options:",
      "  --since <duration>              Policy-event window such as 30m or 8h",
      "  --tail <count>                  Bounded runtime event tail (100..200000)",
      ...common,
    ],
    infrastructure: [
      "Usage: bun scripts/cli.ts platform-infra sub2api codex-pool runtime infrastructure --account <name-or-id> [--group <name-or-id>] [--platform <name>] [--since <duration>] [--target <id>] [--json|--full|--raw]",
      "",
      "Options:",
      "  --account <name-or-id>          Exact account selector",
      "  --group <name-or-id>            Optional group context",
      "  --platform <name>               Optional platform context",
      "  --since <duration>              Recent infrastructure error window",
      ...common,
    ],
    apply: [
      "Usage: bun scripts/cli.ts platform-infra sub2api codex-pool runtime apply (--account <selector>|--accounts <selectors>|--select-configured-policy --account-type apikey) --kind <kind> [kind options] [--confirm] [--target <id>]",
      "",
      "Kinds:",
      "  temp-unschedulable              Requires --template <id>",
      "  priority                        Requires --priority <0-1000>; lower is higher",
      "  capacity                        Requires --capacity <1-100000>; account concurrency guard",
      "  account-name                    Requires one --account and --name <new-name>",
      "",
      "Selection:",
      "  --exclude-accounts <selectors>  Exclude explicit exceptions from configured-policy selection",
      "  --confirm                       Write after reviewing the default dry-run",
      ...common,
    ],
    delete: [
      "Usage: bun scripts/cli.ts platform-infra sub2api codex-pool runtime delete (--account <selector>|--accounts <selectors>|--select-configured-policy --account-type apikey) --kind temp-unschedulable [--confirm] [--target <id>]",
      "",
      "Options:",
      "  --exclude-accounts <selectors>  Exclude explicit exceptions from configured-policy selection",
      "  --confirm                       Write after reviewing the default dry-run",
      ...common,
    ],
  };
  const lines = requested === null
    ? [
      "Usage: bun scripts/cli.ts platform-infra sub2api codex-pool runtime <action> [options]",
      "",
      `Actions: ${actions.join(", ")}`,
      "",
      "Run runtime <action> --help for action-specific options. Help is local and does not submit a remote job.",
    ]
    : actionHelp[requested];
  lines.push("", "STATE mutation=false remoteJobSubmitted=false");
  return {
    ok: true,
    command,
    renderedText: lines.join("\n"),
    contentType: "text/plain",
    projection: { ok: true, mutation: false, remoteJobSubmitted: false, action: requested },
  };
}

function compactRuntimeEvents(parsed: Record<string, unknown> | null): Record<string, unknown> | null {
  if (parsed === null) return null;
  return {
    ok: parsed.ok,
    error: parsed.error,
    operation: parsed.operation,
    source: parsed.source,
    window: parsed.window,
    tail: parsed.tail,
    scannedLineCount: parsed.scannedLineCount,
    policyEventCount: parsed.policyEventCount,
    completionEventCount: parsed.completionEventCount,
    eventCount: parsed.eventCount,
    events: Array.isArray(parsed.events) ? parsed.events : [],
    mutation: false,
    valuesPrinted: false,
  };
}

function compactRuntimeMutationJson(parsed: Record<string, unknown> | null): Record<string, unknown> | null {
  if (parsed === null) return null;
  const items = Array.isArray(parsed.items) ? parsed.items.filter(isRecord) : [];
  const confirmed = parsed.mode === "confirmed";
  return {
    ok: parsed.ok,
    operation: parsed.operation,
    mode: parsed.mode,
    mutation: parsed.mutation,
    partialWrite: parsed.partialWrite,
    selection: parsed.selection,
    summary: parsed.summary,
    items: items.map((item) => {
      const write = isRecord(item.write) ? item.write : {};
      const desiredDiffers = JSON.stringify(item.desired) !== JSON.stringify(item.before);
      return {
        accountName: item.accountName,
        accountId: item.accountId,
        selectionReason: item.selectionReason,
        change: item.change,
        template: item.template,
        before: item.before,
        desired: desiredDiffers ? item.desired : null,
        actual: confirmed ? item.actual : undefined,
        writeStatus: write.status,
        writeError: write.error,
        reconciled: item.reconciled,
        reconcileError: item.reconcileError,
      };
    }),
    credentialsPrinted: false,
    valuesPrinted: false,
  };
}
