import { Hono } from 'hono';
import type { Bindings } from '../types';
import { handleCypherSearch, handleCypherExecute } from '../actions/cypher-handlers';
import { searchByTarget } from '../actions/target-search';

export const cypherRouter = new Hono<{ Bindings: Bindings }>();

const VALID_TARGETS = new Set(['component', 'recipe', 'workflow']);

// POST /cypher/search — 三元組 → 解析節點 → 語意搜尋零件 → 回傳 Cypher JSON (開發友善格式)
//
// t159（leo 07-31）：加 `target` 指定搜尋對象（component／recipe／workflow）＋`query` 名字搜尋。
//   - triplets（不給 target）＝混搜兩庫＋意圖節點替換（步驟 4）
//   - triplets + target=component|recipe＝只查該庫
//   - query + target＝名字搜尋，各自走**既有**機制（registry search／私庫 RECIPES／workflows/search）
cypherRouter.post('/cypher/search', async (c) => {
  const body = await c.req.json() as { triplets?: unknown; mode?: unknown; target?: unknown; query?: unknown };
  const rawTriplets = body?.triplets;

  // ── target 驗證（component / recipe / workflow）─────────────────────────────
  const target = typeof body?.target === 'string' ? body.target : undefined;
  if (target !== undefined && !VALID_TARGETS.has(target)) {
    return c.json({ error: `target 只接受 component／recipe／workflow，收到「${target}」` }, 400);
  }

  // ── query 名字搜尋分支（需 target）──────────────────────────────────────────
  const query = typeof body?.query === 'string' ? body.query.trim() : '';
  if (query) {
    if (!target) {
      return c.json({ error: '給 query 必須同時給 target（component／recipe／workflow），指明要搜哪個庫' }, 400);
    }
    const apiKey = c.req.header('X-Arcrun-API-Key') ?? undefined;
    const r = await searchByTarget(target as 'component' | 'recipe' | 'workflow', query, c.env, apiKey);
    if (!r.ok) return c.json({ error: r.error }, r.status);
    return c.json(r.body);
  }

  if (!Array.isArray(rawTriplets) || rawTriplets.length === 0) {
    return c.json({ error: 'triplets 必須為非空字串陣列（或給 query + target 做名字搜尋）' }, 400);
  }

  // t158「部署≠發現」：mode=compile＝純編圖（安裝器/acr push 的複製路徑，零存在性查詢）；
  // 預設 discover＝誠實查詢（AI 問「有沒有」的既有契約，not_found＋指路照舊）。
  const mode = body?.mode === 'compile' ? 'compile' : 'discover';

  // target 限庫只屬於 discover（compile＝純複製，不查任何庫，target 無意義）
  if (target && mode === 'compile') {
    return c.json({ error: 'mode=compile（複製路徑）不查庫，不接受 target；要指定搜尋對象請用 discover（預設）' }, 400);
  }
  // workflow 是名字搜尋，不參與三元組編圖——請帶 query
  if (target === 'workflow') {
    return c.json({ error: 'target=workflow 是名字搜尋，請改帶 { target: "workflow", query: "..." }（不吃 triplets）' }, 400);
  }

  try {
    const now = new Date();
    const timestamp = now.toISOString();
    const versionId = `search-v1-${now.getFullYear()}${String(now.getMonth() + 1).padStart(2, '0')}${String(now.getDate()).padStart(2, '0')}-${String(now.getHours()).padStart(2, '0')}${String(now.getMinutes()).padStart(2, '0')}${String(now.getSeconds()).padStart(2, '0')}`;

    const result = await handleCypherSearch(rawTriplets, c.env, mode, target as 'component' | 'recipe' | undefined);

    const response = {
      version: versionId,
      timestamp,
      triplets: rawTriplets,
      nodes: result.nodes,
      cypher: result.cypher,
      missing: result.missing,
    };

    return c.json(response);
  } catch (err) {
    const errMsg = err instanceof Error ? err.message : String(err);
    return c.json({ error: errMsg }, 400);
  }
});

// POST /cypher/execute — 三元組 → 一步執行（search + execute 合一）
cypherRouter.post('/cypher/execute', async (c) => {
  const body = await c.req.json() as {
    triplets?: unknown;
    context?: Record<string, unknown>;
    config?: Record<string, Record<string, unknown>>;  // node_name → {component, ...params}
    graph_id?: string;
    graph_name?: string;
  };

  if (!Array.isArray(body?.triplets) || body.triplets.length === 0) {
    return c.json({ error: 'triplets 必須為非空字串陣列' }, 400);
  }

  const graphId = typeof body.graph_id === 'string' ? body.graph_id : `triplet-exec-${Date.now()}`;
  const graphName = typeof body.graph_name === 'string' ? body.graph_name : 'Triplet Execution';
  const now = new Date();
  const timestamp = now.toISOString();
  // 版本號格式：execute-v1-20260327-143022
  const versionId = `execute-v1-${now.getFullYear()}${String(now.getMonth() + 1).padStart(2, '0')}${String(now.getDate()).padStart(2, '0')}-${String(now.getHours()).padStart(2, '0')}${String(now.getMinutes()).padStart(2, '0')}${String(now.getSeconds()).padStart(2, '0')}`;

  const apiKey = c.req.header('X-Arcrun-API-Key') ?? undefined;

  try {
    const result = await handleCypherExecute(
      body.triplets as unknown[],
      body.context,
      graphId,
      graphName,
      body.config,
      c.env,
      (p) => c.executionCtx.waitUntil(p),
      apiKey,
    );
    // 包裝成開發友善格式（execute 成功時）
    const response = {
      version: versionId,
      timestamp,
      ...result,
    };
    return c.json(response);
  } catch (err) {
    const errMsg = err instanceof Error ? err.message : String(err);
    try {
      const parsed = JSON.parse(errMsg);
      const response = {
        version: versionId,
        timestamp,
        ...parsed,
      };
      return c.json(response, 500);
    } catch {
      return c.json({ version: versionId, timestamp, success: false, error: errMsg, duration_ms: 0 }, 500);
    }
  }
});
