export const dynamic = 'force-dynamic';
import { NextRequest, NextResponse } from "next/server";
import {
  ListOpenTasksRequestSchema,
  ClaimTaskRequestSchema,
  SubmitSolutionRequestSchema,
  CreateSubTaskRequestSchema,
  TaskStatus,
  JudgeOverallResult
} from "@agent-bounty/contracts";
import { isIP } from "node:net";
import { prisma } from "@/lib/prisma";
import { runSubmissionInSandbox } from "@/lib/sandbox";
import { broadcastFomoEvent } from "@/lib/x-broadcaster";
import { logAuditEvent } from "@/lib/audit";
import { redis } from "@/lib/redis";
import { authHold, capturePayment } from "@/lib/payment";
import { sendTrafficAlert } from "@/lib/traffic-alert";
import { evaluateExternalFunnelHealth } from "@/lib/traffic-conversion-monitor";
import crypto from "crypto";
import { z } from "zod";

const MCP_SURGE_WINDOW_MINUTES = 10;
const MCP_SURGE_INTERVAL = 25;
const AUTO_WHITELIST_EXTERNAL_AGENTS = (process.env.AUTO_WHITELIST_EXTERNAL_AGENTS || "false").toLowerCase() === "true";
const REQUEST_ID_HEADER_NAMES = ["x-request-id", "x-correlation-id", "x-trace-id"];

const MCP_AGENT_HEADERS = [
  "x-agent-id",
  "x-agent-name",
  "x-client-id",
  "x-request-id",
  "x-mcp-agent-id",
  "x-openai-agent",
];

function asRecordJson(value: unknown): Record<string, unknown> | undefined {
  if (typeof value === "object" && value !== null && !Array.isArray(value)) {
    return value as Record<string, unknown>;
  }
  return undefined;
}

function resolveRequestId(request: NextRequest) {
  for (const headerName of REQUEST_ID_HEADER_NAMES) {
    const value = request.headers.get(headerName);
    if (value) {
      return value;
    }
  }
  return crypto.randomUUID();
}

function summarizeRequestPayload(tool: string, payload: unknown) {
  const body = asRecordJson(payload) || {};

  if (tool === "claim_task") {
    return {
      tool,
      task_id: typeof body.task_id === "string" ? body.task_id : undefined,
      agent_id: typeof body.agent_id === "string" ? body.agent_id : undefined,
      has_developer_wallet: typeof body.developer_wallet === "string",
    };
  }

  if (tool === "submit_solution") {
    return {
      tool,
      task_id: typeof body.task_id === "string" ? body.task_id : undefined,
      claim_token_prefix:
        typeof body.claim_token === "string" ? body.claim_token.slice(0, 10) : undefined,
      deliverable_count:
        typeof body.deliverables === "object" &&
        body.deliverables !== null &&
        !Array.isArray(body.deliverables)
          ? Object.keys(body.deliverables).length
          : undefined,
    };
  }

  if (tool === "list_open_tasks") {
    return {
      tool,
      has_body: body && Object.keys(body).length > 0,
    };
  }

  return {
    tool,
    keys: Object.keys(body),
  };
}

function resolveRequestTrace(request: NextRequest) {
  return {
    request_id: resolveRequestId(request),
    source_ip: resolveSourceIp(request),
    user_agent: request.headers.get("user-agent") ?? "unknown",
    request_actor_headers: {
      x_agent_id: request.headers.get("x-agent-id") ?? null,
      x_agent_name: request.headers.get("x-agent-name") ?? null,
      x_client_id: request.headers.get("x-client-id") ?? null,
      x_openai_agent: request.headers.get("x-openai-agent") ?? null,
      x_mcp_agent_id: request.headers.get("x-mcp-agent-id") ?? null,
      x_request_id: request.headers.get("x-request-id") ?? null,
      origin: request.headers.get("origin") ?? null,
    },
  };
}

function sanitizeIpAddress(value: string | undefined) {
  if (!value) {
    return undefined;
  }

  const first = value.split(",")[0]?.trim();
  if (!first) {
    return undefined;
  }

  const bracketedMatch = first.match(/^\[(.+)\]:(\d+)$/);
  if (bracketedMatch?.[1]) {
    return bracketedMatch[1].toLowerCase();
  }

  const ipv4WithPortMatch = first.match(/^(\d{1,3}(?:\.\d{1,3}){3}):\d+$/);
  if (ipv4WithPortMatch?.[1]) {
    return ipv4WithPortMatch[1];
  }

  return first.toLowerCase();
}

function resolveSourceIp(request: NextRequest) {
  return sanitizeIpAddress(
    request.headers.get("x-forwarded-for") ??
    request.headers.get("x-real-ip") ??
    request.headers.get("cf-connecting-ip") ??
    request.headers.get("true-client-ip") ??
    request.headers.get("x-client-ip") ??
    "unknown"
  );
}

async function ensureBuilderAgent(
  agentId: string,
  requestContext?: {
    request_id?: string;
    source_ip?: string;
    user_agent?: string;
    request_actor_headers?: Record<string, unknown>;
  }
) {
  const existingAgent = await prisma.agentProfile.findUnique({ where: { agent_id: agentId } });
  if (existingAgent) {
    return existingAgent;
  }

  if (!AUTO_WHITELIST_EXTERNAL_AGENTS) {
    return null;
  }

  try {
    const created = await prisma.agentProfile.create({
      data: {
        agent_id: agentId,
        type: "BUILDER",
        status: "WHITELISTED",
      },
    });

    void sendTrafficAlert({
      level: "info",
      action: "EXTERNAL_AGENT_AUTO_WHITELIST",
      surface: "mcp/claim_task",
      actorType: "AGENT",
      actorId: `agent:${normalizeActorId(agentId, "agent")}`,
      message: `外部 Agent 首次接案已自動白名單: ${agentId}`,
      metadata: {
        ...requestContext,
        agent_id: agentId,
      },
    });

    return created;
  } catch (error: unknown) {
    // In high-concurrency case, another request may create the same agent first.
    const isUniqueViolation =
      typeof error === "object" &&
      error !== null &&
      "code" in error &&
      (error as { code?: unknown }).code === "P2002";

    if (isUniqueViolation) {
      return prisma.agentProfile.findUnique({ where: { agent_id: agentId } });
    }

    throw error;
  }
}

function isPrivateIp(ip: string | undefined) {
  if (!ip) return true;
  const normalized = ip.trim().toLowerCase();
  if (!normalized || normalized === "unknown" || normalized === "localhost") {
    return true;
  }
  if (normalized === "::1" || normalized.startsWith("fe80")) {
    return true;
  }
  if (isIP(normalized) === 6 && (normalized.startsWith("fc") || normalized.startsWith("fd"))) {
    return true;
  }
  if (isIP(normalized) === 0) {
    return false;
  }

  if (normalized.startsWith("127.") || normalized.startsWith("10.") || normalized.startsWith("192.168.")) {
    return true;
  }

  if (normalized.startsWith("172.")) {
    const secondOctet = Number(normalized.split(".")[1]);
    return secondOctet >= 16 && secondOctet <= 31;
  }

  return false;
}

function normalizeActorId(value: string, fallback: string) {
  const normalized = value.trim().toLowerCase().replace(/[^a-z0-9._:-]+/g, "_").replace(/_+/g, "_");
  return normalized.slice(0, 64) || fallback;
}

function resolveActorFromMcpRequest(request: NextRequest) {
  for (const headerName of MCP_AGENT_HEADERS) {
    const headerValue = request.headers.get(headerName);
    if (headerValue) {
      return {
        actorType: "AGENT" as const,
        actorId: `agent:${normalizeActorId(headerValue, "agent")}`,
      };
    }
  }

  return {
    actorType: "AGENT" as const,
    actorId: "mcp-anonymous",
  };
}

export async function POST(request: NextRequest, props: { params: Promise<{ tool: string }> }) {
  const params = await props.params;
  const tool = params.tool;
  const actor = resolveActorFromMcpRequest(request);
  const requestContext = resolveRequestTrace(request);

  const authHeader = request.headers.get("Authorization");
  if (!authHeader || !authHeader.startsWith("Bearer ")) {
    void sendTrafficAlert({
      level: "warning",
      action: "EXTERNAL_MCP_AUTH_MISSING",
      surface: `mcp/${tool}`,
      actorType: actor.actorType,
      actorId: actor.actorId,
      taskId: "open-tasks",
      message: "缺少 MCP Authorization Bearer Token",
      metadata: {
        ...requestContext,
        auth_issue: "missing_bearer_token",
        payload_summary: summarizeRequestPayload(tool, null),
        response_summary: "missing_bearer_token",
        response_status: 401,
      },
    });

    return NextResponse.json({ error: "Unauthorized: Missing Bearer token" }, { status: 401 });
  }

  const token = authHeader.split(" ")[1];
  
  // 試營運推廣期間，允許外部 Agent 使用這組公版 Token 來接案
  const isBetaToken = token === "vw_beta_promo_2026";
  const isValidServerKey = process.env.API_KEY && token === process.env.API_KEY;

  if (!isValidServerKey && !isBetaToken) {
    void sendTrafficAlert({
      level: "warning",
      action: "EXTERNAL_MCP_AUTH_FORBIDDEN",
      surface: `mcp/${tool}`,
      actorType: actor.actorType,
      actorId: actor.actorId,
      taskId: "open-tasks",
      message: "MCP Authorization Bearer Token 無效",
      metadata: {
        ...requestContext,
        auth_issue: "invalid_bearer_token",
        response_summary: "invalid_bearer_token",
        response_status: 403,
      },
    });

    return NextResponse.json({ error: "Forbidden: Invalid API Key" }, { status: 403 });
  }

  let body: unknown = null;
  const responseStatusMap: Record<string, number> = {
    list_open_tasks: 200,
    claim_task: 200,
    submit_solution: 200,
    check_payout_status: 200,
  };
  try {
    body = await request.json();

    switch (tool) {
      case "list_open_tasks": {
        if (typeof body === "object" && body !== null && !("skills" in body)) {
          (body as Record<string, unknown>).skills = [];
        }
        ListOpenTasksRequestSchema.parse(body);
        const sourceIp = resolveSourceIp(request);
        const isPublicIp = !isPrivateIp(sourceIp);
        const trafficAction = isPublicIp ? "EXTERNAL_LIST_OPEN_TASKS_MCP" : "INTERNAL_LIST_OPEN_TASKS_MCP";
        const tasks = await prisma.task.findMany({
          where: {
            status: TaskStatus.OPEN,
            title: {
              not: {
                startsWith: "GitHub Issue:",
              },
            },
          },
        });
        const sampleTaskIds = tasks.slice(0, 20).map((task) => task.id);

        const formattedTasks = tasks.map((t) => ({
          task_id: t.id,
          title: t.title,
          status: t.status,
          difficulty: t.difficulty,
          reward: {
            amount: t.reward_amount,
            currency: t.reward_currency,
            display_amount: `$${(t.reward_amount / 100).toFixed(2)}`
          },
          required_stack: t.required_stack,
          scope_clarity_score: t.scope_clarity_score,
          created_at: t.created_at.toISOString(),
          description_preview: t.description.substring(0, 100) + (t.description.length > 100 ? "..." : ""),
        }));

        void sendTrafficAlert({
          level: "info",
          action: trafficAction,
          surface: "mcp/list_open_tasks",
          actorType: actor.actorType,
          actorId: actor.actorId,
          taskId: "open-tasks",
          message: "外部 MCP 查詢任務列表",
          metadata: {
            count: formattedTasks.length,
            sample_task_ids: sampleTaskIds,
            source_tool: tool,
            ...requestContext,
            payload_summary: summarizeRequestPayload(tool, body),
            response_summary: `list_open_tasks_ok:${formattedTasks.length}`,
            response_status: responseStatusMap[tool] || 200,
          },
        });

        if (isPublicIp) {
          void evaluateExternalFunnelHealth({
            surface: "mcp/list_open_tasks",
            periodMinutes: 10,
          });
        }

        void prisma.auditEvent.count({
          where: {
            createdAt: {
              gte: new Date(Date.now() - MCP_SURGE_WINDOW_MINUTES * 60 * 1000),
            },
            action: trafficAction,
          },
        }).then((eventCount) => {
          if (eventCount > 0 && eventCount % MCP_SURGE_INTERVAL === 0) {
            void sendTrafficAlert({
              level: "warning",
              action: isPublicIp ? "EXTERNAL_LIST_OPEN_TASKS_SURGE" : "INTERNAL_LIST_OPEN_TASKS_SURGE",
              surface: "mcp/list_open_tasks",
              actorType: "SYSTEM",
              actorId: "traffic-monitor",
              taskId: "open-tasks",
              message: `MCP list_open_tasks spike detected: ${eventCount} hits in ${MCP_SURGE_WINDOW_MINUTES}m`,
              metadata: {
                alert_window_minutes: MCP_SURGE_WINDOW_MINUTES,
                event_count: eventCount,
                source_tool: tool,
                response_summary: `open_tasks_surge_${MCP_SURGE_WINDOW_MINUTES}m:${eventCount}`,
              },
            });
          }
        }).catch(() => {});

        return NextResponse.json({
          tasks: formattedTasks,
          total_open: formattedTasks.length,
          stockout_warning: formattedTasks.length === 0,
        });
      }

      case "claim_task": {
        const parsed = ClaimTaskRequestSchema.parse(body);

        // Verify Agent Whitelist
        const agent = await ensureBuilderAgent(parsed.agent_id, requestContext);
        if (!agent) {
          void sendTrafficAlert({
            level: "warning",
            action: "EXTERNAL_CLAIM_TASK_FORBIDDEN",
            surface: "mcp/claim_task",
            actorType: "AGENT",
            actorId: `agent:${normalizeActorId(parsed.agent_id, "agent")}`,
            taskId: parsed.task_id,
            message: `外部 Agent 嘗試接案但尚未白名單: ${parsed.agent_id}`,
            metadata: {
              developer_wallet: parsed.developer_wallet,
              ...requestContext,
              payload_summary: summarizeRequestPayload(tool, body),
              response_summary: "claim_forbidden_not_whitelisted",
              response_status: 403,
            },
          });
          return NextResponse.json({ error: "Forbidden: Agent is not whitelisted" }, { status: 403 });
        }

        if (agent.status !== "WHITELISTED") {
          void sendTrafficAlert({
            level: "warning",
            action: "EXTERNAL_CLAIM_TASK_FORBIDDEN",
            surface: "mcp/claim_task",
            actorType: "AGENT",
            actorId: `agent:${normalizeActorId(parsed.agent_id, "agent")}`,
            taskId: parsed.task_id,
            message: `external agent 狀態非白名單: ${parsed.agent_id}`,
            metadata: {
              developer_wallet: parsed.developer_wallet,
              ...requestContext,
              payload_summary: summarizeRequestPayload(tool, body),
              response_summary: `claim_forbidden_status_${agent.status}`,
              response_status: 403,
            },
          });
          return NextResponse.json({ error: "Forbidden: Agent is not whitelisted" }, { status: 403 });
        }
        
        const claim = await prisma.$transaction(async (tx) => {
          const updated = await tx.task.updateMany({
            where: { id: parsed.task_id, status: TaskStatus.OPEN },
            data: { status: TaskStatus.EXECUTING, builder_id: agent.agent_id }
          });
          
          if (updated.count === 0) {
            throw new Error("Task is not OPEN or does not exist");
          }

          const task = await tx.task.findUniqueOrThrow({ where: { id: parsed.task_id } });

          const newClaim = await tx.claim.create({
            data: {
              task_id: task.id,
              agent_id: agent.agent_id,
              developer_wallet: parsed.developer_wallet,
              status: TaskStatus.EXECUTING,
              claim_token: crypto.randomUUID(),
              held_amount: task.reward_amount,
              held_currency: task.reward_currency,
              expires_at: new Date(Date.now() + 3600000)
            }
          });
          
          await authHold(
            tx, 
            task.id, 
            task.reward_amount, 
            task.reward_currency, 
            parsed.developer_wallet, 
            `${newClaim.id}-auth-hold`
          );

          await logAuditEvent(tx, {
            actorType: "AGENT",
            actorId: parsed.developer_wallet,
            action: "CLAIM_TASK",
            entityType: "TASK",
            entityId: task.id,
            beforeState: { status: TaskStatus.OPEN },
            afterState: { status: TaskStatus.EXECUTING }
          });
          
          return newClaim;
        });

        void sendTrafficAlert({
          level: "info",
          action: "EXTERNAL_CLAIM_TASK_SUCCESS",
          surface: "mcp/claim_task",
          actorType: "AGENT",
          actorId: `agent:${normalizeActorId(parsed.agent_id, "agent")}`,
          taskId: claim.task_id,
          message: `Agent 成功接案: ${parsed.task_id}`,
          metadata: {
            ...requestContext,
            agent_id: parsed.agent_id,
            reward: claim.held_amount,
            currency: claim.held_currency,
            claim_token_prefix: claim.claim_token.slice(0, 10),
            payload_summary: summarizeRequestPayload(tool, body),
            response_summary: "claim_success",
            response_status: responseStatusMap[tool] || 200,
          },
        });

        void evaluateExternalFunnelHealth({
          surface: "mcp/claim_task",
          periodMinutes: 10,
        });

        // Set Redis TTL key (3600 seconds)
        await redis.set(`vw:task:${claim.task_id}:executing`, claim.claim_token, "EX", 3600);

        return NextResponse.json({
          task_id: claim.task_id,
          status: claim.status,
          held_amount: claim.held_amount,
          held_currency: claim.held_currency,
          expires_at: claim.expires_at.toISOString(),
          claim_token: claim.claim_token,
          request_id: requestContext.request_id,
        });
      }

      case "submit_solution": {
        const parsed = SubmitSolutionRequestSchema.parse(body);
        
        const result = await prisma.$transaction(async (tx) => {
          const claim = await tx.claim.findUnique({ where: { claim_token: parsed.claim_token } });
          if (!claim || claim.task_id !== parsed.task_id || claim.status !== TaskStatus.EXECUTING) {
            throw new Error("Invalid claim token or claim is not EXECUTING");
          }

          const updatedTask = await tx.task.updateMany({
            where: { id: parsed.task_id, status: TaskStatus.EXECUTING },
            data: { status: TaskStatus.VERIFYING }
          });

          if (updatedTask.count === 0) {
            throw new Error("Task is not EXECUTING");
          }

          await tx.claim.update({
            where: { id: claim.id },
            data: { status: TaskStatus.VERIFYING }
          });

          const newSubmission = await tx.submission.create({
            data: {
              task_id: parsed.task_id,
              claim_id: claim.id,
              status: TaskStatus.VERIFYING,
              deliverables: parsed.deliverables as any,
              estimated_judge_complete_at: new Date(Date.now() + 300000)
            }
          });
          
          await logAuditEvent(tx, {
            actorType: "AGENT",
            action: "SUBMIT_SOLUTION",
            entityType: "TASK",
            entityId: parsed.task_id,
            beforeState: { status: TaskStatus.EXECUTING },
            afterState: { status: TaskStatus.VERIFYING }
          });
          
          return {
            submission: newSubmission,
            claim,
          };
        });
        const { submission, claim: submittedClaim } = result;

        void sendTrafficAlert({
          level: "info",
          action: "EXTERNAL_SUBMIT_SOLUTION_SUCCESS",
          surface: "mcp/submit_solution",
          actorType: "AGENT",
          actorId: submittedClaim.agent_id,
          taskId: submission.task_id,
          message: `Agent 提交解法: ${parsed.task_id}`,
          metadata: {
            ...requestContext,
            actor_id: submittedClaim.agent_id,
            claim_id: submission.claim_id,
            deliverable_count: Object.keys(parsed.deliverables ?? {}).length,
            submission_id: submission.id,
            payload_summary: summarizeRequestPayload(tool, body),
            response_summary: "submit_success",
            response_status: responseStatusMap[tool] || 200,
          },
        });

        void evaluateExternalFunnelHealth({
          surface: "mcp/submit_solution",
          periodMinutes: 10,
        });

        // Async trigger E2B Sandbox evaluation
        const taskObj = await prisma.task.findUnique({ where: { id: submission.task_id }});
        if (taskObj && typeof taskObj.acceptance_criteria === "object" && taskObj.acceptance_criteria !== null) {
          const criteria = taskObj.acceptance_criteria as any;
          if (criteria.test_file_content) {
            // Fire and forget
            runSubmissionInSandbox(
              submission.id,
              parsed.deliverables as unknown as Record<string, string>,
              criteria.test_file_content
            ).then(async (result) => {
              await prisma.$transaction(async (tx) => {
                // Update submission
                await tx.submission.update({
                  where: { id: submission.id },
                  data: { status: "JUDGED" }
                });

                // Create JudgeResult
                await tx.judgeResult.create({
                  data: {
                    submission_id: submission.id,
                    overall_result: result.overall_result,
                    tests: result.tests,
                    artifacts: result.artifacts,
                    error_classification: result.error_classification,
                    resource_usage: result.resource_usage
                  }
                });

                // Update Task & Claim Status
                const newTaskStatus = result.overall_result === JudgeOverallResult.PASS 
                  ? TaskStatus.PENDING_REVIEW 
                  : TaskStatus.FAILED_RETRYABLE;
                  
                await tx.task.update({
                  where: { id: submission.task_id },
                  data: { 
                    status: newTaskStatus,
                    github_pr_url: parsed.github_pr_url
                  }
                });

                await tx.claim.update({
                  where: { id: submission.claim_id },
                  data: { status: newTaskStatus }
                });
                
                await logAuditEvent(tx, {
                  actorType: "SYSTEM",
                  action: "JUDGE_COMPLETE",
                  entityType: "TASK",
                  entityId: submission.task_id,
                  beforeState: { status: TaskStatus.VERIFYING },
                  afterState: { status: newTaskStatus },
                  metadata: { overall_result: result.overall_result, error_classification: result.error_classification }
                });
              });

              // SPEED_RUN FOMO Broadcaster
              if (result.overall_result === JudgeOverallResult.PASS) {
                const solveTimeMs = new Date().getTime() - new Date(taskObj.created_at).getTime();
                const solveTimeMinutes = Math.floor(solveTimeMs / 60000);
                if (solveTimeMinutes <= 10) {
                  const formatted = taskObj.reward_currency === "USD" 
                    ? `$${(taskObj.reward_amount / 100).toFixed(0)}` 
                    : `NT$${taskObj.reward_amount}`;
                  void broadcastFomoEvent({
                    type: "SPEED_RUN",
                    taskId: taskObj.id,
                    amountFormatted: formatted,
                    timeToSolveMinutes: Math.max(1, solveTimeMinutes)
                  });
                }
              }

            }).catch(console.error);
          }
        }
        
        return NextResponse.json({
          task_id: submission.task_id,
          submission_id: submission.id,
          status: submission.status,
          estimated_judge_complete_at: submission.estimated_judge_complete_at?.toISOString() ?? new Date().toISOString(),
          request_id: requestContext.request_id,
        });
      }

      case "create_sub_task": {
        const parsed = CreateSubTaskRequestSchema.parse(body);
        
        const subTask = await prisma.$transaction(async (tx) => {
          const claim = await tx.claim.findUnique({ where: { claim_token: parsed.claim_token } });
          if (!claim || claim.task_id !== parsed.parent_task_id || claim.status !== TaskStatus.EXECUTING) {
            throw new Error("Invalid claim token or parent task is not EXECUTING");
          }
          if (parsed.reward_amount >= claim.held_amount) {
             throw new Error("Sub-task reward cannot exceed parent task reward");
          }

          const newTask = await tx.task.create({
            data: {
              title: `[Sub-Task] ${parsed.title}`,
              description: parsed.description,
              status: TaskStatus.OPEN,
              difficulty: "HELLO_WORLD",
              reward_amount: parsed.reward_amount,
              reward_currency: claim.held_currency,
              required_stack: ["A2A", "Agent Sub-Task"],
              scope_clarity_score: 1.0,
              parent_task_id: parsed.parent_task_id,
              created_by_agent: claim.agent_id,
              acceptance_criteria: parsed.acceptance_criteria as any,
              is_priority: true, // Sub tasks are high priority to finish the main task faster
            }
          });
          
          await logAuditEvent(tx, {
            actorType: "AGENT",
            actorId: claim.agent_id,
            action: "CREATE_SUB_TASK",
            entityType: "TASK",
            entityId: newTask.id,
            beforeState: null,
            afterState: { status: TaskStatus.OPEN, parent: claim.task_id }
          });

          return newTask;
        });

        void sendTrafficAlert({
          level: "info",
          action: "EXTERNAL_CREATE_SUB_TASK_SUCCESS",
          surface: "mcp/create_sub_task",
          actorType: "AGENT",
          actorId: subTask.created_by_agent!,
          taskId: subTask.id,
          message: `A2A 內循環！Agent 發佈了子任務: ${subTask.id}`,
          metadata: {
            parent_task_id: parsed.parent_task_id,
            reward: parsed.reward_amount,
            payload_summary: summarizeRequestPayload(tool, body),
          }
        });

        // A2A Subcontracting FOMO
        const formatted = subTask.reward_currency === "USD"
          ? `$${(subTask.reward_amount / 100).toFixed(0)}`
          : `NT$${subTask.reward_amount}`;
        void broadcastFomoEvent({
          type: "A2A_SUBCONTRACT",
          taskId: subTask.id,
          amountFormatted: formatted
        });

        return NextResponse.json({
          sub_task_id: subTask.id,
          status: subTask.status,
          request_id: requestContext.request_id,
        });
      }

      case "check_payout_status": {
        const parsed = z.object({ task_id: z.string().uuid() }).parse(body);

        const task = await prisma.task.findUnique({ where: { id: parsed.task_id } });
        if (!task) {
          throw new Error("Task not found");
        }

        const ledger = await prisma.ledgerEntry.findFirst({
          where: { task_id: parsed.task_id },
          orderBy: { created_at: 'desc' }
        });

        if (!ledger) {
          void sendTrafficAlert({
            level: "info",
            action: "EXTERNAL_CHECK_PAYOUT_STATUS_SUCCESS",
            surface: "mcp/check_payout_status",
            actorType: actor.actorType,
            actorId: actor.actorId,
            taskId: task.id,
            message: `Payout 資料未就緒: ${task.id}`,
          metadata: {
            ...requestContext,
            payload_summary: summarizeRequestPayload(tool, body),
            response_summary: "payout_status_not_ready",
            ledger_phase: "NO_LEDGER",
            response_status: responseStatusMap[tool] || 200,
          },
          });
          return NextResponse.json({
            task_id: task.id,
            phase: task.status === "COMPLETED" ? "PAYOUT_READY" : "NO_LEDGER",
            amount: task.reward_amount,
            currency: task.reward_currency,
            updated_at: task.updated_at.toISOString(),
            request_id: requestContext.request_id,
          });
        }

        void sendTrafficAlert({
          level: "info",
          action: "EXTERNAL_CHECK_PAYOUT_STATUS_SUCCESS",
          surface: "mcp/check_payout_status",
          actorType: actor.actorType,
          actorId: actor.actorId,
          taskId: task.id,
          message: `Payout 查詢成功: ${task.id}`,
          metadata: {
            ...requestContext,
            payload_summary: summarizeRequestPayload(tool, body),
            response_summary: `payout_status_${ledger.phase}`,
            ledger_phase: ledger.phase,
            response_status: responseStatusMap[tool] || 200,
          },
        });

        return NextResponse.json({
          task_id: task.id,
          phase: ledger.phase,
          amount: task.reward_amount,
          currency: task.reward_currency,
          updated_at: ledger.updated_at.toISOString(),
          ledger_entry: ledger,
          request_id: requestContext.request_id,
        });
      }

      default:
        void sendTrafficAlert({
          level: "warning",
          action: "EXTERNAL_MCP_TOOL_UNKNOWN",
          surface: `mcp/${tool}`,
          actorType: actor.actorType,
          actorId: actor.actorId,
          taskId: "open-tasks",
          message: `未知 MCP tool: ${tool}`,
          metadata: {
            ...requestContext,
            payload_summary: summarizeRequestPayload(tool, body),
            response_summary: "mcp_tool_unknown",
            response_status: 404,
          },
        });
        return NextResponse.json({ error: `Unknown tool: ${tool}` }, { status: 404 });
    }
  } catch (error: any) {
    console.error(`[API Gateway] Error handling ${tool}:`, error);
    const payloadSummary = summarizeRequestPayload(tool, body);
    const actorInCatch = resolveActorFromMcpRequest(request);
    const catchContext = resolveRequestTrace(request);
    const isStateConflict =
      typeof error === "object" &&
      error !== null &&
      "message" in error &&
      typeof (error as { message?: string }).message === "string" &&
      ["not OPEN", "not EXECUTING", "Invalid claim token", "not found", "Task is not OPEN or does not exist", "Task is not EXECUTING"].some(
        (token) => (error as { message?: string }).message?.includes(token)
      );
    const responseStatus = error instanceof SyntaxError || error.name === "ZodError" ? 400 : isStateConflict ? 409 : 500;

    void sendTrafficAlert({
      level: "error",
      action: `EXTERNAL_${tool.toUpperCase()}_ERROR`,
      surface: `mcp/${tool}`,
      actorType: "AGENT",
      actorId: actorInCatch.actorId,
      taskId:
        typeof body === "object" && body !== null && "task_id" in body
          ? String((body as { task_id?: string }).task_id ?? "unknown")
          : "unknown",
      message: `${error instanceof Error ? error.message : String(error)}`,
      metadata: {
        ...catchContext,
        payload_summary: payloadSummary,
        response_summary: `${tool}_error`,
        error_name: error?.name ?? "Error",
        error_message: error instanceof Error ? error.message : String(error),
        response_status: responseStatus,
      },
    });
    
    if (error.name === "ZodError") {
      return NextResponse.json({ error_type: "InvalidParams", message: error.errors }, { status: 400 });
    }
    
    const msg = error.message || String(error);
    if (msg.includes("not OPEN") || msg.includes("not EXECUTING") || msg.includes("Invalid claim token") || msg.includes("not found")) {
      return NextResponse.json({ error_type: "StateConflict", message: msg }, { status: responseStatus });
    }

    return NextResponse.json({ error_type: "InternalError", message: msg }, { status: responseStatus });
  }
}
