import { Hono } from 'hono';
import type { Bindings, ExecutionGraph } from '../types';
import { ExecutionError } from '../types';
import { GraphExecutor } from '../graph-executor';
import { executeSchema } from '../lib/schemas';
import { createComponentLoader } from '../lib/component-loader';
import { writeExecutionVerdict } from '../actions/execution-logger';

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

// POST /execute — 執行一個完整的圖
executeRouter.post('/execute', async (c) => {
  const body = await c.req.json();
  const parsed = executeSchema.safeParse(body);
  if (!parsed.success) {
    return c.json({ error: '圖定義驗證失敗', details: parsed.error.issues }, 400);
  }

  const { graph, context } = parsed.data;
  const apiKey = c.req.header('x-arcrun-api-key') ?? undefined;
  const loader = createComponentLoader(c.env);
  const executor = new GraphExecutor(loader, undefined, c.env, apiKey);
  const start = Date.now();

  try {
    // BUILD-006：傳入 KV namespace（若不存在則 fallback 到記憶體 merge）
    const result = await executor.execute(graph as ExecutionGraph, context, c.env.EXEC_CONTEXT);
    const duration_ms = Date.now() - start;
    c.executionCtx.waitUntil(
      writeExecutionVerdict(c.env, graph.id, graph.nodes, 'success', duration_ms, '執行完成', context, apiKey)
    );
    return c.json({ success: true, data: result.data, trace: result.trace, duration_ms });
  } catch (err) {
    const duration_ms = Date.now() - start;
    const errMsg = err instanceof Error ? err.message : String(err);
    c.executionCtx.waitUntil(
      writeExecutionVerdict(c.env, graph.id, graph.nodes, 'failed', duration_ms, errMsg.slice(0, 100), context, apiKey)
    );
    if (err instanceof ExecutionError) {
      const traceFormatted = err.trace.map(s => ({
        node: s.nodeId,
        status: s.error ? 'failed' : 'success',
        ...(s.error ? { error: s.error } : {}),
      }));
      return c.json({
        success: false,
        error: errMsg,
        failed_node: err.failed_node,
        failed_input: err.failed_input,
        trace: traceFormatted,
        duration_ms,
      }, 500);
    }
    return c.json({ success: false, error: errMsg, failed_node: null, trace: [], duration_ms }, 500);
  }
});
