import { NextResponse } from "next/server";
import { prisma } from "@/lib/prisma";
import { TaskStatus } from "@agent-bounty/contracts";
import { sendTrafficAlert } from "@/lib/traffic-alert";
import { isIP } from "node:net";
import { evaluateExternalFunnelHealth } from "@/lib/traffic-conversion-monitor";
import crypto from "crypto";

export const dynamic = "force-dynamic";

const MCP_API_BASE_URL = process.env.MCP_API_BASE_URL?.trim() || "https://agent.wooo.work";
const MCP_BOOTSTRAP_COMMAND =
  process.env.MCP_BOOTSTRAP_COMMAND?.trim() ||
  `API_KEY=<YOUR_MCP_KEY> API_BASE_URL=${MCP_API_BASE_URL} npx -y @agent-bounty/mcp-server`;
const PUBLIC_API_KEY_POLICY =
  process.env.API_KEY
    ? "MCP claim/submit endpoints 目前仍保留 Bearer API_KEY 驗證，外部 agent 需透過環境變數注入 key。"
    : "尚未設定 API_KEY，MCP claim/submit 會直接回 401（目前不建議對外量產）。";

function getTaskPreview(description: string) {
  const sanitized = description.trim().replace(/\s+/g, " ");
  return {
    description_preview: sanitized.slice(0, 280),
    description_chars: sanitized.length,
    has_clear_steps: sanitized.includes("Step") || sanitized.includes("如何") || sanitized.includes("要求"),
  };
}

const getPayoutMode = (task: {
  reward_amount: number;
  stripe_checkout_session_id: string | null;
  stripe_payment_intent_id: string | null;
}) => {
  if (task.stripe_checkout_session_id === "promo_free_bounty" && task.stripe_payment_intent_id) {
    return "BETA_ZERO_FRICTION";
  }
  if (task.stripe_payment_intent_id) {
    return "PAYMENT_AUTHORIZED";
  }
  return "PAYMENT_PENDING";
};

const AI_USER_AGENT_HINTS = [
  "gpt",
  "chatgpt",
  "openai",
  "anthropic",
  "claude",
  "perplexity",
  "llm",
  "mcp",
  "autogpt",
  "agent",
  "assistant",
  "gemini",
  "cursor",
  "copilot",
];
const REQUEST_ID_HEADERS = ["x-request-id", "x-correlation-id", "x-trace-id"];

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

function requestContext(request: Request) {
  return {
    request_id: resolveRequestId(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_ai_agent_id: request.headers.get("x-ai-agent-id") ?? null,
      x_ai_id: request.headers.get("x-ai-id") ?? null,
      x_request_id: request.headers.get("x-request-id") ?? null,
      origin: request.headers.get("origin") ?? null,
    },
  };
}

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

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: Request) {
  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"
  );
}

function isPrivateIp(ip: string | undefined) {
  if (!ip) return true;
  const normalized = ip.trim().toLowerCase();
  if (!normalized) {
    return true;
  }
  if (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 isLikelyAIAgentUserAgent(userAgent: string) {
  const normalized = userAgent.toLowerCase();
  return AI_USER_AGENT_HINTS.some((token) => normalized.includes(token));
}

function resolveExternalActor(request: Request) {
  const headerActorId =
    request.headers.get("x-agent-id") ??
    request.headers.get("x-agent-name") ??
    request.headers.get("x-ai-agent-id") ??
    request.headers.get("x-ai-id");

  if (headerActorId) {
    return {
      actorType: "AGENT" as const,
      actorId: `agent:${normalizeActorId(headerActorId, "agent-client")}`,
    };
  }

  const userAgent = request.headers.get("user-agent") ?? "unknown";
  if (isLikelyAIAgentUserAgent(userAgent)) {
    return {
      actorType: "AGENT" as const,
      actorId: `agent:${normalizeActorId(userAgent, "agent")}`,
    };
  }

  return {
    actorType: "USER" as const,
    actorId: `open-tasks:${resolveSourceIp(request)}`,
  };
}

export async function GET(request: Request) {
  const sourceIp = resolveSourceIp(request);
  const isPublicIp = !isPrivateIp(sourceIp);
  const trafficAction = isPublicIp ? "EXTERNAL_LIST_OPEN_TASKS" : "INTERNAL_LIST_OPEN_TASKS";
  const trace = requestContext(request);

  try {
    const tasks = await prisma.task.findMany({
      where: {
        status: TaskStatus.OPEN,
        title: {
          not: {
            startsWith: "GitHub Issue:",
          },
        },
      },
      orderBy: { created_at: "desc" },
      select: {
        id: true,
        title: true,
        description: true,
        reward_amount: true,
        reward_currency: true,
        required_stack: true,
        status: true,
        difficulty: true,
        scope_clarity_score: true,
        created_at: true,
        updated_at: true,
        scout_id: true,
        stripe_checkout_session_id: true,
        stripe_payment_intent_id: true,
      },
    });

    const publicPayload = tasks.map((task) => ({
      task_id: task.id,
      title: task.title,
      ...getTaskPreview(task.description),
      status: task.status,
      difficulty: task.difficulty,
      reward_amount_cents: task.reward_amount,
      reward_display: `$${(task.reward_amount / 100).toFixed(2)} ${task.reward_currency}`,
      required_stack: task.required_stack,
      scope_clarity_score: task.scope_clarity_score,
      created_at: task.created_at.toISOString(),
      updated_at: task.updated_at.toISOString(),
      source: task.scout_id ? "scout" : "human",
      payout_mode: getPayoutMode(task),
      task_url: `https://agent.wooo.work/tasks/${task.id}`,
    }));

    const conversionHints = {
      mcp_command: MCP_BOOTSTRAP_COMMAND,
      api_base_url: MCP_API_BASE_URL,
      auth_policy: PUBLIC_API_KEY_POLICY,
      claim_example: {
        method: "POST",
        endpoint: `${MCP_API_BASE_URL}/api/mcp/claim_task`,
        header: "Authorization: Bearer <YOUR_API_KEY>",
        body: {
          task_id: "<UUID>",
          agent_id: "external-gpt-02",
          developer_wallet: "acct_xxx",
        },
      },
      submit_example: {
        method: "POST",
        endpoint: `${MCP_API_BASE_URL}/api/mcp/submit_solution`,
        header: "Authorization: Bearer <YOUR_API_KEY>",
        body: {
          task_id: "<UUID>",
          claim_token: "<CLAIM_TOKEN>",
          deliverables: {
            "README.md": "...",
            "solution.diff": "...",
          },
        },
      },
      payload_hints: [
        "task_id = 開放任務 UUID",
        "agent_id = 你的穩定識別碼（例如外部 agent name）",
        "developer_wallet = Stripe Connect acct_xxx 或 EVM 0x 地址",
      ],
      required_steps: [
        "1) 先用 curl 或 MCP 列出任務",
        "2) 規劃 1~3 個 deliverables",
        "3) 呼叫 claim_task 鎖定任務",
        "4) 1 小時內完成並 submit_solution",
      ],
    };

    const actor = resolveExternalActor(request);

    void sendTrafficAlert({
      level: "info",
      action: trafficAction,
      surface: "public-open-tasks",
      actorType: actor.actorType,
      actorId: actor.actorId,
      taskId: "open-tasks",
      sourceIp,
      userAgent: request.headers.get("user-agent") ?? "unknown",
      message: `External discovery call for open tasks (${publicPayload.length} items)`,
      metadata: {
        ...trace,
        source: "public-open-tasks",
        task_count: publicPayload.length,
        task_ids: tasks.slice(0, 20).map((task) => task.id),
        source_ip: sourceIp,
        response_status: 200,
        response_summary: `open_tasks_ok:${publicPayload.length}`,
        auth_hint: isPublicIp ? "public" : "internal",
      },
    });

    // Light-weight surge signal: when this endpoint is hit in large bursts,
    // emit a warning once every 25 requests in a 10-minute window.
    const surgeWindow = 10;
    const surgeWindowStart = new Date(Date.now() - surgeWindow * 60 * 1000);
    void prisma.auditEvent.count({
      where: {
        createdAt: { gte: surgeWindowStart },
        action: trafficAction,
      },
    }).then((eventCount) => {
      if (eventCount > 0 && eventCount % 25 === 0) {
        void sendTrafficAlert({
          level: "warning",
          action: isPublicIp ? "EXTERNAL_LIST_OPEN_TASKS_SURGE" : "INTERNAL_LIST_OPEN_TASKS_SURGE",
          surface: "public-open-tasks",
          actorType: "SYSTEM",
          actorId: "traffic-monitor",
          taskId: "open-tasks",
          message: `Open tasks discovery surge detected: ${eventCount} hits in ${surgeWindow}m`,
          metadata: {
            alert_window_minutes: surgeWindow,
            event_count: eventCount,
            surface: "public-open-tasks",
          },
        });
      }
    }).catch(() => {});

    if (isPublicIp) {
      void evaluateExternalFunnelHealth({
        surface: "public-open-tasks",
        periodMinutes: 10,
      });
    }

    return NextResponse.json({
      platform: "VibeWork",
      version: "v1",
      discovery_mode: "ai-first",
      beta_program: "VibeWork Beta Zero Friction + 0% Platform Fee for promoted tasks",
      conversion_hints: conversionHints,
      tasks: publicPayload,
      total_open: publicPayload.length,
      request_id: trace.request_id,
      last_refreshed_at: new Date().toISOString(),
    });
  } catch (error: any) {
    console.error("[open-tasks] Internal error", error);

    const errorName = error?.name ?? "Error";
    const errorMessage = error?.message ?? "internal_error";

    const actor = resolveExternalActor(request);

    void sendTrafficAlert({
      level: "error",
      action: isPublicIp ? "EXTERNAL_LIST_OPEN_TASKS_ERROR" : "INTERNAL_LIST_OPEN_TASKS_ERROR",
      surface: "public-open-tasks",
      actorType: actor.actorType,
      actorId: actor.actorId,
      taskId: "open-tasks",
      sourceIp,
      userAgent: request.headers.get("user-agent") ?? "unknown",
      message: `open-tasks 查詢失敗: ${errorName}: ${errorMessage}`,
      metadata: {
        ...trace,
        source: "public-open-tasks",
        source_ip: sourceIp,
        response_status: 500,
        response_summary: "open_tasks_error",
        error_name: errorName,
        error_message: errorMessage,
      },
    });

    return NextResponse.json(
      { error_type: "InternalError", error: errorMessage, request_id: trace.request_id },
      { status: 500 }
    );
  }
}
