/**
 * POST /workflows/resume
 * Webhook callback 進來時，從 paused state 撿起來繼續跑下游節點
 * SDD: matrix/arcrun/.agents/specs/resumable-workflow/design.md Phase 3
 *
 * 安全：因為這是 daemon 主動 callback，沒有 partner key（daemon 不知道用戶 key）
 *      靠 task_id 為 nonce + 24h TTL + idempotent consume 保護
 */

import { Hono } from 'hono';
import type { Bindings } from '../types';
import { WorkflowPaused } from '../types';
import { GraphExecutor } from '../graph-executor';
import { createComponentLoader } from '../lib/component-loader';
import { consumePausedRun } from '../lib/paused-runs';

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

resumeRouter.post('/workflows/resume', async (c) => {
  let body: Record<string, unknown>;
  try {
    body = await c.req.json();
  } catch {
    return c.json({ error: 'request body 必須為 JSON' }, 400);
  }

  const taskId = typeof body.task_id === 'string' ? body.task_id : undefined;
  if (!taskId) {
    return c.json({ error: 'task_id 必填' }, 400);
  }

  // consume = load + delete（idempotent：重複 callback 第二次找不到 state，回 200）
  const state = await consumePausedRun(c.env.EXEC_CONTEXT, taskId);
  if (!state) {
    return c.json({
      success: true,
      noop: true,
      reason: `paused state 不存在或已過期 (task_id=${taskId})`,
    });
  }

  const callbackResult = {
    success: body.success ?? true,
    data: body.data,
    error: body.error,
  };

  const loader = createComponentLoader(c.env);
  const executor = new GraphExecutor(loader, undefined, c.env, state.api_key);
  const start = Date.now();

  try {
    const result = await executor.resumeFromPaused({
      graph: state.graph,
      paused_node_id: state.paused_node_id,
      paused_context: state.paused_context,
      callback_result: callbackResult,
      prior_trace: state.trace_so_far,
      kvNamespace: c.env.EXEC_CONTEXT,
      recipe_output_format: state.recipe_output_format,
      recipe_output_required_fields: state.recipe_output_required_fields,
    });
    const duration_ms = Date.now() - start;
    return c.json({
      success: true,
      resumed: true,
      task_id: taskId,
      run_id: state.run_id,
      data: result.data,
      trace: result.trace,
      duration_ms,
    });
  } catch (err) {
    if (err instanceof WorkflowPaused) {
      // resume 後又遇到 pending（v2 nested 情境）— v1 仍持久化但回 paused-again
      return c.json({
        success: true,
        paused_again: true,
        task_id: err.task_id,
        run_id: err.run_id,
        paused_node_id: err.paused_node_id,
      });
    }
    const errMsg = err instanceof Error ? err.message : String(err);
    return c.json({ success: false, error: errMsg, task_id: taskId, run_id: state.run_id }, 500);
  }
});
