// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. accounts module for scripts/src/platform-infra-sub2api-codex.ts.

// Moved mechanically from scripts/src/platform-infra-sub2api-codex.ts:4209-4264 for #903.

import { chmodSync, copyFileSync, existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
import { homedir } from "node:os";
import { join } from "node:path";
import type { UniDeskConfig } from "../config";
import { rootPath } from "../config";
import type { RenderedCliResult } from "../output";
import { applyPk01CaddyBlock, prepareFrpcSecret, renderFrpcManifest, type PublicServiceExposure, type PublicServiceTarget } from "../platform-infra-public-service";
import { shortSha256Fingerprint } from "../platform-infra-ops-library";
import {
  codexPoolSentinelSummary,
  codexPoolSentinelRuntimeImage,
  readCodexPoolSentinelConfig,
  renderCodexPoolSentinelManifest,
  type CodexPoolSentinelConfig,
  type CodexPoolSentinelProfileSecret,
} from "../platform-infra-sub2api-codex-sentinel";
import { parseEnvFile, readTextFile, redactRepoPath, requiredEnvValue } from "../secrets";
import { runSshCommandCapture, type SshCaptureResult } from "../ssh";

import type { CodexPoolConfig, OpenAIResponsesWebSocketsV2Mode } from "./types";
import { renderSub2ApiTempUnschedulableCredentials, uniqueAccountName } from "./redaction";

export function desiredAccountNames(pool: CodexPoolConfig): string[] {
  return Object.keys(desiredAccountCapacityMap(pool)).sort();
}

export function desiredAccountCapacityTotal(pool: CodexPoolConfig): number {
  return Object.values(desiredAccountCapacityMap(pool)).reduce((total, value) => total + value, 0);
}

export function desiredAccountCapacityMap(pool: CodexPoolConfig): Record<string, number> {
  const codexDir = join(homedir(), ".codex");
  const seenAccountNames = new Set<string>();
  const capacities: Record<string, number> = {};
  for (const entry of pool.profiles) {
    const accountName = entry.accountName ?? uniqueAccountName(entry.profile, seenAccountNames);
    seenAccountNames.add(accountName);
    capacities[accountName] = entry.capacity ?? pool.defaultAccountCapacity;
  }
  return capacities;
}

export function desiredAccountLoadFactorMap(pool: CodexPoolConfig): Record<string, number> {
  const codexDir = join(homedir(), ".codex");
  const seenAccountNames = new Set<string>();
  const loadFactors: Record<string, number> = {};
  for (const entry of pool.profiles) {
    const accountName = entry.accountName ?? uniqueAccountName(entry.profile, seenAccountNames);
    seenAccountNames.add(accountName);
    loadFactors[accountName] = entry.loadFactor ?? pool.defaultAccountLoadFactor;
  }
  return loadFactors;
}

export function desiredAccountWebSocketsV2ModeMap(pool: CodexPoolConfig): Record<string, OpenAIResponsesWebSocketsV2Mode | null> {
  const codexDir = join(homedir(), ".codex");
  const seenAccountNames = new Set<string>();
  const modes: Record<string, OpenAIResponsesWebSocketsV2Mode | null> = {};
  for (const entry of pool.profiles) {
    const accountName = entry.accountName ?? uniqueAccountName(entry.profile, seenAccountNames);
    seenAccountNames.add(accountName);
    modes[accountName] = entry.openaiResponsesWebSocketsV2Mode;
  }
  return modes;
}

export function desiredAccountTempUnschedulableMap(pool: CodexPoolConfig): Record<string, unknown> {
  const codexDir = join(homedir(), ".codex");
  const seenAccountNames = new Set<string>();
  const policies: Record<string, unknown> = {};
  for (const entry of pool.profiles) {
    const accountName = entry.accountName ?? uniqueAccountName(entry.profile, seenAccountNames);
    seenAccountNames.add(accountName);
    policies[accountName] = renderSub2ApiTempUnschedulableCredentials(entry.tempUnschedulable);
  }
  return policies;
}

export function desiredDefaultAccountTempUnschedulable(pool: CodexPoolConfig): Record<string, unknown> {
  return renderSub2ApiTempUnschedulableCredentials(pool.defaultTempUnschedulable);
}
