/**
 * acr creds push/list/replace/delete
 *
 * 寫入路徑＝「明文值 + TLS 傳輸」，值交由 CF Workers Secrets 託管。CLI 是薄殼：
 * list/replace/delete 三支指令全部只做「讀 argv/yaml → 呼叫 cypher-executor API →
 * 印結果」，不做任何加解密或業務邏輯（rule 07 薄殼原則）。
 *
 * 移除任何「印出 credential 值」的路徑（D19：擁有目錄，不擁有內容物，連 owner 都讀不回）。
 */
import { readFileSync } from 'node:fs';
import yaml from 'js-yaml';
import chalk from 'chalk';
import ora from 'ora';
import { loadConfig, getCypherExecutorUrl, type ArcrunConfig } from '../lib/config.js';

function requireApiKey(config: ArcrunConfig): string {
  if (!config.api_key) {
    if (config.mode === 'self-hosted') {
      console.error(chalk.red('缺少 NAMESPACE（你的資料分區標籤）。'));
      console.log(chalk.gray('在專案 .env 設一行（明碼即可，這是分區標籤不是密碼）：'));
      console.log(chalk.cyan('  NAMESPACE=leo'));
    } else {
      console.error(chalk.red('缺少 api_key，請重新執行 acr init。'));
    }
    process.exit(1);
  }
  return config.api_key;
}

interface CredentialRow {
  name: string;
  service: string | null;
  sensitivity: string;
  created_at: number;
  last_used_at: number | null;
}

/** acr creds list — 讀 D1 目錄顯示（不含值，D19：讀不回內容物）。 */
export async function cmdCredsList(): Promise<void> {
  const config = loadConfig();
  const apiKey = requireApiKey(config);
  const baseUrl = getCypherExecutorUrl(config);

  const res = await fetch(`${baseUrl}/credentials`, {
    headers: { 'X-Arcrun-API-Key': apiKey },
  });
  const body = (await res.json().catch(() => null)) as
    | { success?: boolean; credentials?: CredentialRow[]; error?: string }
    | null;

  if (!res.ok || !body?.success) {
    console.error(chalk.red(`讀取失敗：${body?.error ?? `HTTP ${res.status}`}`));
    process.exit(1);
  }

  const rows = body.credentials ?? [];
  if (rows.length === 0) {
    console.log(chalk.gray('（尚無 credential）'));
    return;
  }
  console.log(chalk.bold(`\n  ${rows.length} 個 credential（只顯示目錄，值不可讀回）\n`));
  for (const r of rows) {
    const lastUsed = r.last_used_at ? new Date(r.last_used_at * 1000).toISOString() : '（從未使用）';
    console.log(`  ${chalk.cyan(r.name)}  service=${r.service ?? '-'}  sensitivity=${r.sensitivity}  last_used=${lastUsed}`);
  }
  console.log();
}

/** acr creds replace <name> <value> — 整筆覆寫（只能 replace，不能 edit 局部，D19/§3）。 */
export async function cmdCredsReplace(
  name: string,
  value: string,
  options: { service?: string; sensitivity?: string },
): Promise<void> {
  const config = loadConfig();
  const apiKey = requireApiKey(config);
  const baseUrl = getCypherExecutorUrl(config);

  const spinner = ora(`  覆寫 ${name}`).start();
  try {
    const res = await fetch(`${baseUrl}/credentials/${encodeURIComponent(name)}`, {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json', 'X-Arcrun-API-Key': apiKey },
      body: JSON.stringify({ value, service: options.service, sensitivity: options.sensitivity }),
    });
    const body = (await res.json().catch(() => null)) as { success?: boolean; error?: string } | null;
    if (!res.ok || !body?.success) {
      throw new Error(body?.error ?? `HTTP ${res.status}`);
    }
    spinner.succeed(chalk.green(`  ✓ ${name} 已覆寫`));
  } catch (e) {
    spinner.fail(chalk.red(`  ✗ ${name} 失敗：${e instanceof Error ? e.message : e}`));
    process.exit(1);
  }
}

/** acr creds delete <name> — 刪除 credential（目錄 row + Workers Secret 本體）。 */
export async function cmdCredsDelete(name: string): Promise<void> {
  const config = loadConfig();
  const apiKey = requireApiKey(config);
  const baseUrl = getCypherExecutorUrl(config);

  const spinner = ora(`  刪除 ${name}`).start();
  try {
    const res = await fetch(`${baseUrl}/credentials/${encodeURIComponent(name)}`, {
      method: 'DELETE',
      headers: { 'X-Arcrun-API-Key': apiKey },
    });
    const body = (await res.json().catch(() => null)) as { success?: boolean; error?: string } | null;
    if (!res.ok || !body?.success) {
      throw new Error(body?.error ?? `HTTP ${res.status}`);
    }
    spinner.succeed(chalk.green(`  ✓ ${name} 已刪除`));
  } catch (e) {
    spinner.fail(chalk.red(`  ✗ ${name} 失敗：${e instanceof Error ? e.message : e}`));
    process.exit(1);
  }
}

/**
 * acr creds push [credentials.yaml] —（保留 bulk 匯入的既有慣用法，內部改走新的明文 PUT
 * 路徑，不再 client 端 AES-GCM 加密——舊實作對應的 server 格式已被 T5 取代，直接沿用會 400）。
 */
export async function cmdCredsPush(filePath: string): Promise<void> {
  const config = loadConfig();
  const apiKey = requireApiKey(config);

  let creds: Record<string, string>;
  try {
    const raw = readFileSync(filePath, 'utf8');
    creds = yaml.load(raw) as Record<string, string>;
  } catch (e) {
    console.error(chalk.red(`無法讀取 ${filePath}：${e instanceof Error ? e.message : e}`));
    process.exit(1);
  }

  const entries = Object.entries(creds).filter(([, v]) => typeof v === 'string' && v.length > 0);
  if (entries.length === 0) {
    console.log(chalk.yellow('credentials.yaml 中沒有有效的 credential（請取消注解並填入值）'));
    return;
  }

  const baseUrl = getCypherExecutorUrl(config);
  console.log(chalk.bold(`\n  上傳 ${entries.length} 個 credentials 至 ${baseUrl}\n`));

  for (const [name, value] of entries) {
    const spinner = ora(`  ${name}`).start();
    try {
      const res = await fetch(`${baseUrl}/credentials`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'X-Arcrun-API-Key': apiKey },
        body: JSON.stringify({ name, value: String(value) }),
      });
      if (!res.ok) {
        const errBody = await res.text().catch(() => '');
        throw new Error(`HTTP ${res.status}: ${errBody.slice(0, 200)}`);
      }
      spinner.succeed(chalk.green(`  ✓ ${name}`));
    } catch (e) {
      spinner.fail(chalk.red(`  ✗ ${name}  失敗：${e instanceof Error ? e.message : e}`));
    }
  }

  console.log(chalk.gray('\n  Credential 已存進 Workers Secrets（cypher 唯寫，讀不回值）。執行 workflow 時會自動注入。\n'));
}
