/**
 * acr kbdb — KBDB 資料層 CLI 薄殼（kbdb-base Phase 9.2，HANDOFF §2）
 *
 *   acr kbdb template create <name> --slots a,b,c   建 template（虛擬表定義）
 *   acr kbdb template list                          列出所有 template
 *   acr kbdb record create <template> --values k=v…  填一筆 record
 *   acr kbdb record get <record_id>                 取單筆 record
 *   acr kbdb query <template>                        列某 template 下本租戶的 records
 *   acr kbdb search <q>                              關鍵字搜尋（本租戶 LIKE）
 *
 * 薄殼鐵律（rule 07 §5）：能力長在基本盤 API，CLI 只做介面轉換 + 暴露，無業務邏輯。
 * 透過 cypher 的 KBDB proxy（/kbdb/*）達 KBDB——CLI 本來就只認證到 cypher（X-Arcrun-API-Key），
 * 與 MCP 薄殼（kbdb_data.ts）同一組基本盤能力，差異只來自介面慣例（rule 07 §3.4）。
 * KBDB 鐵律：只 template/slot，無建表/SQL（proxy 端也不暴露）。
 */
import chalk from 'chalk';
import ora from 'ora';
import { loadConfig, getCypherExecutorUrl } from '../lib/config.js';

/** 取身份 + cypher URL，缺 api_key/namespace 直接退出（與 recipe.ts 一致）。 */
function ctx(): { url: string; apiKey: string } {
  const config = loadConfig();
  if (!config.api_key) {
    console.error(chalk.red('缺少 API Key / namespace，請先執行 acr init（或設 NAMESPACE）'));
    process.exit(1);
  }
  return { url: getCypherExecutorUrl(config), apiKey: config.api_key };
}

/** 統一 fetch + JSON 解析 + 失敗印錯（薄殼只暴露，不含業務邏輯）。 */
async function call(method: string, path: string, body?: unknown): Promise<unknown> {
  const { url, apiKey } = ctx();
  const res = await fetch(`${url}${path}`, {
    method,
    headers: { 'Content-Type': 'application/json', 'X-Arcrun-API-Key': apiKey },
    body: body ? JSON.stringify(body) : undefined,
  });
  const text = await res.text();
  let data: unknown;
  try { data = text ? JSON.parse(text) : {}; } catch { data = { raw: text }; }
  if (!res.ok) {
    console.error(chalk.red(`KBDB 失敗（HTTP ${res.status}）：${text || '(空回應)'}`));
    process.exit(1);
  }
  return data;
}

/** 把 ["k=v","x=y"] 轉成 { k:"v", x:"y" }。 */
function parseKeyVals(pairs: string[]): Record<string, string> {
  const out: Record<string, string> = {};
  for (const p of pairs) {
    const i = p.indexOf('=');
    if (i < 0) {
      console.error(chalk.red(`--values 格式須為 key=value，收到："${p}"`));
      process.exit(1);
    }
    out[p.slice(0, i)] = p.slice(i + 1);
  }
  return out;
}

// ── template ───────────────────────────────────────────────────────────────────

export async function cmdKbdbTemplateCreate(name: string, opts: { slots?: string }): Promise<void> {
  const slots = (opts.slots ?? '').split(',').map(s => s.trim()).filter(Boolean);
  if (slots.length === 0) {
    console.error(chalk.red('需要 --slots a,b,c（至少一個欄位名）'));
    process.exit(1);
  }
  const spinner = ora(`建 template "${name}"`).start();
  const data = await call('POST', '/kbdb/templates', { name, slots });
  spinner.succeed(chalk.green(`template "${name}" 已建（slots: ${slots.join(', ')}）`));
  console.log(chalk.gray(JSON.stringify(data, null, 2)));
}

export async function cmdKbdbTemplateList(): Promise<void> {
  const data = await call('GET', '/kbdb/templates') as { templates?: Array<{ name: string; slots_json?: string }>; count?: number };
  const list = data.templates ?? [];
  if (list.length === 0) {
    console.log(chalk.yellow('（尚無 template，用 acr kbdb template create <name> --slots … 建一個）'));
    return;
  }
  console.log(chalk.bold(`\n  ${list.length} 個 template：\n`));
  for (const t of list) {
    console.log(`  ${chalk.cyan(t.name)}  ${chalk.gray(t.slots_json ?? '')}`);
  }
  console.log();
}

// ── record ───────────────────────────────────────────────────────────────────

export async function cmdKbdbRecordCreate(template: string, opts: { values?: string[] }): Promise<void> {
  const values = parseKeyVals(opts.values ?? []);
  if (Object.keys(values).length === 0) {
    console.error(chalk.red('需要 --values slot=內容（可重複），如 --values name=Leo --values email=x@y.com'));
    process.exit(1);
  }
  const spinner = ora(`填 record（template "${template}"）`).start();
  const data = await call('POST', '/kbdb/records', { template, values });
  spinner.succeed(chalk.green(`record 已存入 template "${template}"`));
  console.log(chalk.gray(JSON.stringify(data, null, 2)));
}

export async function cmdKbdbRecordGet(recordId: string): Promise<void> {
  const data = await call('GET', `/kbdb/records/${encodeURIComponent(recordId)}`);
  console.log(chalk.gray(JSON.stringify(data, null, 2)));
}

// ── query / search ─────────────────────────────────────────────────────────────

export async function cmdKbdbQuery(template: string): Promise<void> {
  const data = await call('GET', `/kbdb/records/by-template/${encodeURIComponent(template)}`) as { records?: unknown[]; count?: number };
  const recs = data.records ?? [];
  console.log(chalk.bold(`\n  template "${template}" 下 ${recs.length} 筆 record（本租戶）：\n`));
  console.log(chalk.gray(JSON.stringify(recs, null, 2)));
}

export async function cmdKbdbSearch(q: string): Promise<void> {
  const data = await call('GET', `/kbdb/search?q=${encodeURIComponent(q)}`) as { entries?: unknown[]; count?: number; mode?: string };
  const hits = data.entries ?? [];
  console.log(chalk.bold(`\n  "${q}" 命中 ${hits.length} 筆（mode: ${data.mode ?? 'keyword'}，本租戶）：\n`));
  console.log(chalk.gray(JSON.stringify(hits, null, 2)));
}
