import type { UniDeskConfig } from "../config";
import type { RenderedCliResult } from "../output";

import { readCodexPoolConfig } from "./config";
import { renderProfitScenarioLines } from "./profit-scenario-render";
import { boolField, compactCapture, parseJsonOutput, runRemoteCodexPoolScript } from "./remote";
import { profitScript } from "./remote-scripts";
import { codexPoolRuntimeTarget, defaultCodexPoolRuntimeTargetId } from "./runtime-target";

interface ProfitOptions {
  since: string;
  month: string | null;
  forecast: boolean;
  targetId: string;
  json: boolean;
  accounts: boolean;
  missingCosts: boolean;
  pageToken: string | null;
  saleRateCnyPerApiUsd: string | null;
  scenarioWithoutAccounts: string[];
}

const PROFIT_ACCOUNT_PAGE_SIZE = 8;

export async function codexPoolProfit(config: UniDeskConfig, args: string[]): Promise<Record<string, unknown> | RenderedCliResult> {
  const pool = readCodexPoolConfig();
  if (args.includes("--help")) return renderProfitHelp(pool.profit.defaultWindow);
  const options = parseProfitOptions(args, pool.profit.defaultWindow);
  const target = codexPoolRuntimeTarget(options.targetId);
  const scenario = options.saleRateCnyPerApiUsd !== null || options.scenarioWithoutAccounts.length > 0
    ? {
        saleRateCnyPerApiUsd: options.saleRateCnyPerApiUsd ?? String(pool.profit.saleRateCnyPerApiUsd),
        withoutAccounts: options.scenarioWithoutAccounts,
      }
    : null;
  const payload = { since: options.since, month: options.month, forecast: options.forecast, config: pool.profit, scenario };
  const remote = await runRemoteCodexPoolScript(config, "profit", profitScript(payload, pool, target), target);
  const report = parseJsonOutput(remote.stdout);
  const ok = remote.exitCode === 0 && boolField(report, "ok", false);
  const projectedReport = projectProfitReport(report, options);
  const windowOption = options.month === null ? `--since ${options.since}` : `--month ${options.month}${options.forecast ? " --forecast" : ""}`;
  const scenarioOption = [
    options.saleRateCnyPerApiUsd === null ? null : `--sale-rate ${options.saleRateCnyPerApiUsd}`,
    ...options.scenarioWithoutAccounts.map((selector) => `--scenario-without-account ${shellArg(selector)}`),
  ].filter((item): item is string => item !== null).join(" ");
  const baseCommand = `bun scripts/cli.ts platform-infra sub2api codex-pool profit --target ${target.id} ${windowOption}${scenarioOption ? ` ${scenarioOption}` : ""}`;
  const accountPage = record(record(projectedReport).accountPage);
  const response = {
    ok,
    action: "platform-infra-sub2api-codex-pool-profit",
    target: { id: target.id, route: target.route, runtimeMode: target.runtimeMode, endpoint: target.serviceDns },
    source: {
      kind: "sub2api-native-admin-usage",
      mutation: false,
      configPath: "config/platform-infra/sub2api-codex-pool.yaml#profit",
    },
    report: projectedReport,
    disclosure: {
      accountsIncluded: options.accounts,
      missingCostsIncluded: options.missingCosts,
      accountCount: arrayOfRecords(record(report).accounts).length,
      accounts: `${baseCommand} --accounts`,
      accountsNext: accountPage.nextPageToken ? `${baseCommand} --accounts --page-token ${text(accountPage.nextPageToken)}` : null,
      missingCosts: `${baseCommand} --missing-costs`,
      json: `${baseCommand} --json`,
    },
    remote: compactCapture(remote, { full: !ok || report === null }),
    valuesPrinted: false,
  };
  return options.json ? renderProfitJson(response) : renderProfit(response);
}

function parseProfitOptions(args: string[], defaultWindow: string): ProfitOptions {
  let since = defaultWindow;
  let month: string | null = null;
  let forecast = false;
  let targetId = defaultCodexPoolRuntimeTargetId();
  let json = false;
  let accounts = false;
  let missingCosts = false;
  let pageToken: string | null = null;
  let saleRateCnyPerApiUsd: string | null = null;
  const scenarioWithoutAccounts: string[] = [];
  const readValue = (index: number, option: string): [string, number] => {
    const value = args[index + 1];
    if (value === undefined || value.startsWith("--")) throw new Error(`${option} requires a value`);
    return [value.trim(), index + 1];
  };
  for (let index = 0; index < args.length; index += 1) {
    const arg = args[index]!;
    if (arg === "--json") json = true;
    else if (arg === "--forecast") forecast = true;
    else if (arg === "--accounts") accounts = true;
    else if (arg === "--missing-costs") missingCosts = true;
    else if (arg === "--sale-rate") {
      [saleRateCnyPerApiUsd, index] = readValue(index, "--sale-rate");
    } else if (arg.startsWith("--sale-rate=")) saleRateCnyPerApiUsd = arg.slice("--sale-rate=".length).trim();
    else if (arg === "--scenario-without-account") {
      let selector: string;
      [selector, index] = readValue(index, "--scenario-without-account");
      scenarioWithoutAccounts.push(selector);
    } else if (arg.startsWith("--scenario-without-account=")) scenarioWithoutAccounts.push(arg.slice("--scenario-without-account=".length).trim());
    else if (arg === "--month") {
      [month, index] = readValue(index, "--month");
    } else if (arg.startsWith("--month=")) month = arg.slice("--month=".length).trim();
    else if (arg === "--page-token") {
      [pageToken, index] = readValue(index, "--page-token");
    } else if (arg.startsWith("--page-token=")) pageToken = arg.slice("--page-token=".length).trim();
    else if (arg === "--since") {
      [since, index] = readValue(index, "--since");
    } else if (arg.startsWith("--since=")) since = arg.slice("--since=".length).trim();
    else if (arg === "--target") {
      [targetId, index] = readValue(index, "--target");
    } else if (arg.startsWith("--target=")) targetId = arg.slice("--target=".length).trim();
    else throw new Error(`unsupported profit option: ${arg}`);
  }
  if (!/^[1-9][0-9]*(?:s|m|h|d)$/u.test(since)) throw new Error("--since must be a duration such as 24h, 90m, or 7d");
  if (month !== null && !/^\d{4}-(?:0[1-9]|1[0-2])$/u.test(month)) throw new Error("--month must use YYYY-MM");
  if (month !== null && args.some((arg) => arg === "--since" || arg.startsWith("--since="))) throw new Error("use only one of --since or --month");
  if (forecast && month === null) throw new Error("--forecast requires --month YYYY-MM");
  if (!targetId || /[\r\n\0]/u.test(targetId)) throw new Error("--target has an unsupported format");
  if (accounts && missingCosts) throw new Error("--accounts and --missing-costs are separate semantic disclosures");
  if (pageToken !== null && !accounts) throw new Error("--page-token requires --accounts");
  if (pageToken !== null && (!pageToken || /[\r\n\0\s]/u.test(pageToken))) throw new Error("--page-token has an unsupported format");
  if (saleRateCnyPerApiUsd !== null && !/^(?:0|[1-9][0-9]*)(?:\.[0-9]+)?$/u.test(saleRateCnyPerApiUsd)) {
    throw new Error("--sale-rate must be a non-negative decimal CNY per API USD value");
  }
  if (scenarioWithoutAccounts.some((selector) => !selector || /[\r\n\0]/u.test(selector))) {
    throw new Error("--scenario-without-account requires an exact account ID or name");
  }
  const uniqueScenarioAccounts = [...new Set(scenarioWithoutAccounts)];
  return { since, month, forecast, targetId, json, accounts, missingCosts, pageToken, saleRateCnyPerApiUsd, scenarioWithoutAccounts: uniqueScenarioAccounts };
}

function renderProfitHelp(defaultWindow: string): RenderedCliResult {
  return {
    ok: true,
    command: "platform-infra sub2api codex-pool profit --help",
    renderedText: [
      "SUB2API CODEX-POOL PROFIT",
      "Usage:",
      "  bun scripts/cli.ts platform-infra sub2api codex-pool profit [--since 24h|--month YYYY-MM [--forecast]] [--target PK01] [--sale-rate <CNY/API_USD>] [--scenario-without-account <id-or-exact-name> ...] [--accounts [--page-token <token>]|--missing-costs] [--json]",
      "Options:",
      `  --since <duration>  Native usage window; YAML default is ${defaultWindow}.`,
      "  --month <YYYY-MM>  Calendar-month usage plus YAML-declared one-time period costs.",
      "  --forecast         Extrapolate month-to-date variable revenue and costs to month end; period costs remain one-time.",
      "  --target <id>",
      "  --sale-rate <value> Candidate sale price in CNY per API USD; does not change YAML.",
      "  --scenario-without-account <selector> Read-only retirement scenario; repeat for multiple exact account IDs or names.",
      "  --accounts          Include one fixed-size account page with complete names and IDs.",
      "  --page-token <token> Continue from the opaque token returned by the previous account page.",
      "  --missing-costs     Include the missing-cost account list and API USD bases.",
      "  --json              Emit exact structured values.",
      "Notes:",
      "  Default output is a compact summary; use --accounts or --missing-costs for semantic disclosure.",
      "  Retirement scenarios redistribute selected traffic at each class's remaining-account weighted cost rate and report load growth.",
      "  This command is read-only and does not change Sub2API runtime state.",
    ].join("\n"),
    contentType: "text/plain",
  };
}

function renderProfit(response: Record<string, unknown>): RenderedCliResult {
  const report = record(response.report);
  const window = record(report.window);
  const policy = record(report.policy);
  const summary = record(report.summary);
  const completeness = record(report.completeness);
  const confirmedCosts = record(summary.confirmedCostsCny);
  const profitBeforeUnknownCosts = record(summary.profitBeforeUnknownCostsCny);
  const unknownBasis = record(summary.unknownCostBasisApiUsd);
  const formulas = record(summary.profitFormula);
  const disclosure = record(response.disclosure);
  const lines = [
    `SUB2API PROFIT status=${text(report.status)} target=${text(record(response.target).id)} window=${text(window.month ?? window.since)}`,
    `WINDOW ${text(window.startAt)} -> ${text(window.endAt)}  SOURCE native-admin-usage/${text(record(report.source).usageCostField)}`,
    `POLICY sale-rate=${text(policy.saleRateCnyPerApiUsd)}CNY/API_USD account-cost=${text(policy.accountCostSource)}`,
    "",
    "SUMMARY",
  ];
  lines.push(table(
      ["SCOPE", "STATUS", "REVENUE_CNY", "TRAFFIC_COST_CNY", "SELF_USE_COST_CNY", "PERIOD_COST_CNY", "PROFIT_BEFORE_UNKNOWN_COSTS_CNY", "UNKNOWN_API_USD"],
      [
      ["不扣自用", text(record(summary.withoutSelfUse).status), cny(summary.revenueCny), cny(confirmedCosts.profitPool), "-", cny(confirmedCosts.period), cny(profitBeforeUnknownCosts.withoutSelfUse), apiUsd(unknownBasis.profitPool)],
      ["扣除自用", text(record(summary.withSelfUse).status), cny(summary.revenueCny), cny(confirmedCosts.profitPool), cny(confirmedCosts.selfUse), cny(confirmedCosts.period), cny(profitBeforeUnknownCosts.withSelfUse), apiUsd(unknownBasis.total)],
    ],
  ));
  const forecast = record(summary.forecast);
  if (Object.keys(forecast).length > 0) {
    const forecastCosts = record(forecast.costsCny);
    const forecastProfit = record(forecast.profitCny);
    lines.push("", `FULL-MONTH FORECAST method=${text(forecast.method)} scale=${text(forecast.scale)} observed=${text(forecast.observedSeconds)}s full-period=${text(forecast.fullPeriodSeconds)}s`);
    lines.push(table(
      ["SCOPE", "STATUS", "REVENUE_CNY", "TRAFFIC_COST_CNY", "SELF_USE_COST_CNY", "PERIOD_COST_CNY", "FORECAST_PROFIT_CNY"],
      [
        ["不扣自用", text(record(forecast.withoutSelfUse).status), cny(forecast.revenueCny), cny(forecastCosts.profitPool), "-", cny(forecastCosts.period), cny(forecastProfit.withoutSelfUse)],
        ["扣除自用", text(record(forecast.withSelfUse).status), cny(forecast.revenueCny), cny(forecastCosts.profitPool), cny(forecastCosts.selfUse), cny(forecastCosts.period), cny(forecastProfit.withSelfUse)],
      ],
    ));
  }
  lines.push(...renderProfitScenarioLines(record(report.scenario)));
  const periodCosts = arrayOfRecords(report.periodCosts);
  if (periodCosts.length > 0) {
    lines.push("", "PERIOD COSTS");
    lines.push(table(
      ["ID", "PERIOD", "ACCOUNT", "AMOUNT_CNY", "DESCRIPTION"],
      periodCosts.map((row) => [text(row.id), text(row.period), text(row.accountName), cny(row.amountCny), text(row.description)]),
    ));
  }
  lines.push("", "FORMULA");
  lines.push(`- 不扣自用: ${text(formulas.withoutSelfUse)}`);
  lines.push(`- 扣除自用: ${text(formulas.withSelfUse)}`);
  lines.push("", `COMPLETENESS status=${text(report.status)} missing-cost=${text(completeness.missingCostAccountCount)} unclassified=${text(completeness.unclassifiedTrafficCount)} missing-groups=${text(completeness.configuredGroupMissingCount)}`);
  lines.push(`NEXT accounts: ${text(disclosure.accounts)}`);
  lines.push(`NEXT missing-costs: ${text(disclosure.missingCosts)}`);
  const accounts = arrayOfRecords(report.accounts);
  if (accounts.length > 0) {
    lines.push("", "ACCOUNTS");
    lines.push(table(
      ["GROUP", "CLASS", "ACCOUNT", "ID", "REQ", "TOKENS", "API_USD", "COST_CNY/USD", "REVENUE_CNY", "UPSTREAM_CNY", "PROFIT_CNY", "STATUS"],
      accounts.map((row) => [
        text(row.groupName), text(row.class), text(row.accountName), text(row.accountId), text(row.requestCount), compactTokens(row.tokenCount),
        apiUsd(row.apiAmountUsd), text(row.costRateCnyPerApiUsd), cny(row.revenueCny), cny(row.upstreamCostCny), cny(row.profitContributionCny), text(row.completeness),
      ]),
    ));
    const accountPage = record(report.accountPage);
    if (accountPage.nextPageToken) lines.push(`NEXT account-page: ${text(disclosure.accountsNext)}`);
  }
  const missingCosts = arrayOfRecords(completeness.missingCostAccounts);
  if (missingCosts.length > 0) {
    lines.push("", "MISSING COST ACCOUNTS");
    for (const row of missingCosts) lines.push(`- class=${text(row.class)} group=${text(row.groupName)} account=${text(row.accountName)} id=${text(row.accountId)} api-usd=${text(row.apiAmountUsd)}`);
  }
  if (accounts.length > 0 || missingCosts.length > 0) {
    const unclassified = arrayOfRecords(completeness.unclassifiedTraffic);
    const missingGroups = Array.isArray(completeness.configuredGroupsMissingAtRuntime) ? completeness.configuredGroupsMissingAtRuntime : [];
    if (unclassified.length || missingGroups.length) {
      lines.push("", "COMPLETENESS DETAILS");
      for (const row of unclassified) lines.push(`- unclassified-traffic group=${text(row.groupName)} account=${text(row.accountName)} requests=${text(row.requestCount)}`);
      for (const group of missingGroups) lines.push(`- configured-group-missing ${text(group)}`);
    }
  }
  return {
    ok: response.ok === true,
    command: "platform-infra sub2api codex-pool profit",
    renderedText: lines.join("\n"),
    contentType: "text/plain",
    projection: response,
  };
}

function projectProfitReport(report: Record<string, unknown> | null, options: ProfitOptions): Record<string, unknown> | null {
  if (report === null) return null;
  const { accounts: rawAccounts, completeness: rawCompleteness, ...summaryReport } = report;
  const accounts = arrayOfRecords(rawAccounts);
  const completeness = record(rawCompleteness);
  const compactCompleteness = {
    missingCostAccountCount: arrayOfRecords(completeness.missingCostAccounts).length,
    unclassifiedTrafficCount: arrayOfRecords(completeness.unclassifiedTraffic).length,
    configuredGroupMissingCount: Array.isArray(completeness.configuredGroupsMissingAtRuntime) ? completeness.configuredGroupsMissingAtRuntime.length : 0,
  };
  const compactReport = {
    ...summaryReport,
    accountCount: accounts.length,
    completeness: compactCompleteness,
  };
  if (options.missingCosts) {
    return {
      ...compactReport,
      completeness: {
        ...compactCompleteness,
        missingCostAccounts: arrayOfRecords(completeness.missingCostAccounts),
      },
    };
  }
  if (!options.accounts) return compactReport;
  let startIndex = 0;
  if (options.pageToken !== null) {
    const tokenIndex = accounts.findIndex((row) => encodeProfitAccountPageToken(row) === options.pageToken);
    if (tokenIndex < 0) throw new Error(`profit account page token not found: ${options.pageToken}`);
    startIndex = tokenIndex + 1;
  }
  const pageAccounts = accounts.slice(startIndex, startIndex + PROFIT_ACCOUNT_PAGE_SIZE);
  const hasNext = startIndex + pageAccounts.length < accounts.length;
  const nextPageToken = hasNext && pageAccounts.length > 0 ? encodeProfitAccountPageToken(pageAccounts.at(-1)!) : null;
  return {
    ...compactReport,
    accounts: pageAccounts,
    accountPage: {
      pageSize: PROFIT_ACCOUNT_PAGE_SIZE,
      returned: pageAccounts.length,
      nextPageToken,
    },
  };
}

function encodeProfitAccountPageToken(account: Record<string, unknown>): string {
  return Buffer.from(JSON.stringify([
    account.class ?? null,
    account.groupId ?? null,
    account.accountId ?? null,
    account.accountName ?? null,
  ]), "utf8").toString("base64url");
}

function renderProfitJson(response: Record<string, unknown>): RenderedCliResult {
  return {
    ok: response.ok === true,
    command: "platform-infra sub2api codex-pool profit --json",
    renderedText: JSON.stringify(response),
    contentType: "application/json",
    projection: response,
  };
}

function record(value: unknown): Record<string, unknown> {
  return typeof value === "object" && value !== null && !Array.isArray(value) ? value as Record<string, unknown> : {};
}

function arrayOfRecords(value: unknown): Record<string, unknown>[] {
  return Array.isArray(value) ? value.filter((item): item is Record<string, unknown> => typeof item === "object" && item !== null && !Array.isArray(item)) : [];
}

function text(value: unknown): string {
  if (value === null || value === undefined || value === "") return "-";
  return String(value).replace(/[\r\n\t]+/gu, " ");
}

function shellArg(value: string): string {
  return `'${value.replace(/'/gu, `'"'"'`)}'`;
}

function compactTokens(value: unknown): string {
  const numeric = Number(value);
  if (!Number.isFinite(numeric)) return text(value);
  if (Math.abs(numeric) >= 1_000_000_000) return `${(numeric / 1_000_000_000).toFixed(3)}B`;
  if (Math.abs(numeric) >= 1_000_000) return `${(numeric / 1_000_000).toFixed(3)}M`;
  if (Math.abs(numeric) >= 1_000) return `${(numeric / 1_000).toFixed(3)}K`;
  return String(numeric);
}

function apiUsd(value: unknown): string {
  if (value === null || value === undefined || value === "") return "-";
  const numeric = Number(value);
  return Number.isFinite(numeric) ? `$${numeric.toFixed(6)}` : text(value);
}

function cny(value: unknown): string {
  if (value === null || value === undefined || value === "") return "-";
  const numeric = Number(value);
  return Number.isFinite(numeric) ? `¥${numeric.toFixed(6)}` : text(value);
}

function table(headers: string[], rows: string[][]): string {
  if (rows.length === 0) return `${headers.join("  ")}\n-`;
  const widths = headers.map((header, index) => Math.max(header.length, ...rows.map((row) => (row[index] ?? "").length)));
  return [headers, ...rows].map((row) => row.map((cell, index) => cell.padEnd(widths[index]!)).join("  ").trimEnd()).join("\n");
}
