/**
 * acr push <workflow.yaml>
 *
 * 解析 workflow.yaml，透過 /cypher/search 取得執行圖，
 * 然後 POST 至 cypher.arcrun.dev/webhooks/named（帶 X-Arcrun-API-Key）。
 * Server 以 {api_key}:wf:{name} 為 KV key 存入 WEBHOOKS KV。
 *
 * 不再需要用戶的 CF API Token 或 KV Namespace ID。
 */
import chalk from 'chalk';
import ora from 'ora';
import { loadConfig, getCypherExecutorUrl } from '../lib/config.js';
import { loadWorkflowYaml, parseTriplets, validateRelations } from '../lib/yaml-parser.js';

export async function cmdPush(filePath: string): Promise<void> {
  const config = loadConfig();

  if (config.mode === 'local') {
    console.error(chalk.red('Local 模式不支援 acr push（Webhook 部署需要 Standard 模式）。'));
    console.log(chalk.gray('請執行 acr init 取得 API Key，或直接用 acr run 本機測試。'));
    process.exit(1);
  }

  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);
  }

  // 解析 YAML
  const spinner = ora('解析 workflow.yaml').start();
  let workflow;
  try {
    workflow = loadWorkflowYaml(filePath);
    const triplets = parseTriplets(workflow.flow);
    validateRelations(triplets);
    spinner.succeed(`解析完成：${workflow.name}（${triplets.length} 條三元組）`);
  } catch (e) {
    spinner.fail(chalk.red(`解析失敗：${e instanceof Error ? e.message : e}`));
    process.exit(1);
  }

  const executorUrl = getCypherExecutorUrl(config);
  const headers: Record<string, string> = {
    'Content-Type': 'application/json',
    'X-Arcrun-API-Key': config.api_key,
  };

  // 向 /cypher/search 取得執行圖
  const searchSpinner = ora('取得執行圖').start();
  let graph: unknown;
  try {
    // t158「部署≠發現」（leo：「這裡只是複製工作流的 data 過去，沒有要在這裡驗證」）：
    // push＝複製路徑，帶 mode:compile 純編圖——寫錯的 workflow 照樣部署，錯在執行時現形。
    const res = await fetch(`${executorUrl}/cypher/search`, {
      method: 'POST',
      headers,
      body: JSON.stringify({ triplets: workflow.flow, mode: 'compile' }),
    });

    if (!res.ok) {
      const err = await res.text();
      searchSpinner.fail(chalk.red(`執行圖解析失敗（${res.status}）：${err.slice(0, 200)}`));
      process.exit(1);
    }

    const data = await res.json() as { cypher: { nodes: unknown[]; edges: unknown[] }; missing: string[] };
    // t158：push 不看 missing（compile 模式亦恆空）——存在性由執行時 component-loader 決定；
    // 要「先問有沒有」用 acr validate／MCP 查詢（discover 路徑）。

    // 附上 id / name，並將 workflow.config 套入節點（componentId + data）
    const rawGraph = data.cypher as { nodes: Array<{ id: string; componentId?: string; data?: Record<string, unknown> }>; edges: unknown[] };
    const cfg = (workflow.config ?? {}) as Record<string, Record<string, unknown>>;

    const nodes = rawGraph.nodes.map(node => {
      const nodeCfg = cfg[node.id];
      if (!nodeCfg) return node;
      const { component, ...params } = nodeCfg;
      return {
        ...node,
        componentId: typeof component === 'string' ? component : node.componentId,
        data: Object.keys(params).length > 0 ? { ...(node.data ?? {}), ...params } : node.data,
      };
    });

    graph = { id: workflow.name, name: workflow.name, nodes, edges: rawGraph.edges };
    searchSpinner.succeed('執行圖解析完成');
  } catch (e) {
    searchSpinner.fail(chalk.red(`網路錯誤：${e instanceof Error ? e.message : e}`));
    process.exit(1);
  }

  // 暴露 consent 閘已移除（leo 2026-06-29，Arcrun#13）：arcrun 是給 AI 用的系統，
  // push/暴露不再需要人類確認，AI/MCP 隨時可部署。暴露風險由用戶自負（同 n8n 建 webhook）。

  // POST 至 /webhooks/named
  const deploySpinner = ora(`部署 "${workflow.name}" 至 ${executorUrl}`).start();
  try {
    const res = await fetch(`${executorUrl}/webhooks/named`, {
      method: 'POST',
      headers,
      body: JSON.stringify({
        name: workflow.name,
        graph,
        config: workflow.config ?? {},
        description: workflow.description ?? '',
      }),
    });

    if (!res.ok) {
      const err = await res.text();
      deploySpinner.fail(chalk.red(`部署失敗（${res.status}）：${err.slice(0, 200)}`));
      process.exit(1);
    }

    const data = await res.json() as { name: string; webhook_url: string; created_at: string };
    deploySpinner.succeed(chalk.green(`✓ "${workflow.name}" 已部署`));

    // self-hosted：namespace 明碼 → 給「namespace 進 path」的公開 URL（公開表單可直接打，免 header）。
    // standard：仍走 header（平台多租戶，api_key 是密碼不可進 path）。
    if (config.mode === 'self-hosted') {
      const pathUrl = `${executorUrl}/webhooks/named/${config.api_key}/${workflow.name}/trigger`;
      console.log(chalk.bold(`\n  Webhook URL（公開可打，免 header）：${chalk.cyan(pathUrl)}`));
      console.log(chalk.gray('  namespace 在 path 是明碼分區標籤（非密碼）；要防外部濫用請對 webhook 加保護。'));
      console.log('');
      console.log(chalk.gray('  公開表單 / curl 觸發：'));
      console.log(`  ${chalk.cyan(`curl -X POST ${pathUrl} \\`)}`);
      console.log(`  ${chalk.cyan(`  -H 'Content-Type: application/json' -d '{"key": "value"}'`)}`);
    } else {
      console.log(chalk.bold(`\n  Webhook URL：${chalk.cyan(data.webhook_url)}`));
      console.log(chalk.gray(`  需帶 Header：X-Arcrun-API-Key: ${config.api_key.slice(0, 8)}...`));
      console.log('');
      console.log(chalk.gray('  curl 觸發範例：'));
      console.log(`  ${chalk.cyan(`curl -X POST ${data.webhook_url} \\`)}`);
      console.log(`  ${chalk.cyan(`  -H 'X-Arcrun-API-Key: ${config.api_key}' \\`)}`);
      console.log(`  ${chalk.cyan(`  -H 'Content-Type: application/json' -d '{"key": "value"}'`)}`);
    }
    console.log('');
    console.log(chalk.gray('  測試執行：') + ` ${chalk.cyan(`acr run ${workflow.name}`)}`);
    console.log('');
  } catch (e) {
    deploySpinner.fail(chalk.red(`部署失敗：${e instanceof Error ? e.message : e}`));
    process.exit(1);
  }
}
