import { Hono } from 'hono';
import type { Bindings } from '../types';
import { generateToken, validateAndParseWebhook, executeWebhookGraph } from '../actions/webhook-handlers';
import { resolveWebhookGraph } from '../actions/webhook-graph-resolver';
import { writeExecutionVerdict } from '../actions/execution-logger';

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

type WebhookRecord = {
  graph: Record<string, unknown>;
  description: string;
  created_at: string;
};

// POST /webhooks — 接受 graph、triplets 或直接 nodes/edges
webhooksRouter.post('/webhooks', async (c) => {
  const body = await c.req.json().catch(() => null);
  if (!body) return c.json({ error: 'invalid json' }, 400);

  const description = typeof body.description === 'string' ? body.description : '';
  const resolved = await resolveWebhookGraph(body as Record<string, unknown>, description, c.env);

  if (resolved.error) {
    return c.json({ error: resolved.error }, 400);
  }

  const token = generateToken();
  const record: WebhookRecord = {
    graph: resolved.resolvedGraph,
    description,
    created_at: new Date().toISOString(),
  };

  await c.env.WEBHOOKS.put(token, JSON.stringify(record));

  const baseUrl = new URL(c.req.url).origin;
  return c.json({
    token,
    webhook_url: `${baseUrl}/webhooks/${token}/trigger`,
    description: record.description,
    created_at: record.created_at,
  }, 201);
});

// POST /webhooks/:token/trigger — 觸發執行
webhooksRouter.post('/webhooks/:token/trigger', async (c) => {
  const token = c.req.param('token');
  if (!token || token.length < 16) {
    return c.json({ error: 'invalid token' }, 400);
  }

  const raw = await c.env.WEBHOOKS.get(token, 'text');
  if (!raw) return c.json({ error: 'webhook not found' }, 404);

  const record = await validateAndParseWebhook(raw);
  if (!record) return c.json({ error: 'webhook 定義損毀' }, 500);

  let triggerContext: Record<string, unknown> = {};
  try {
    const body = await c.req.json().catch(() => null);
    if (body && typeof body === 'object') {
      triggerContext = body as Record<string, unknown>;
    }
  } catch {
    // 無 body 時使用空 context
  }

  const apiKey = c.req.header('X-Arcrun-API-Key') ?? undefined;
  const result = await executeWebhookGraph(c.env, record.graph, triggerContext, token, apiKey);

  // fire-and-forget analytics（不阻擋回應）
  const graph = record.graph as { id?: string; nodes?: unknown[] };
  const workflowId = graph.id ?? token;
  const nodes = Array.isArray(graph.nodes) ? (graph.nodes as import('../types').GraphNode[]) : [];
  c.executionCtx.waitUntil(
    writeExecutionVerdict(c.env, workflowId, nodes, result.success ? 'success' : 'failed', result.duration_ms, result.error ?? '', triggerContext, apiKey),
  );

  return c.json(result, result.success ? 200 : 500);
});
