import { NextRequest, NextResponse } from 'next/server';

/**
 * POST /api/error-report
 *
 * 클라이언트 에러를 수신하여 Slack Webhook으로 전송
 * - 서버 측 스로틀링: 동일 에러 30초 쿨다운
 * - Webhook URL 미설정 시 조용히 실패
 */

interface ErrorReport {
  errorType: 'ERROR_BOUNDARY' | 'CHUNK_LOAD_ERROR';
  message: string;
  pageUrl: string;
  timestamp: string;
  digest?: string;
  stack?: string;
  userAgent?: string;
}

const VALID_TYPES = new Set(['ERROR_BOUNDARY', 'CHUNK_LOAD_ERROR']);
const SERVER_COOLDOWN_MS = 30_000;
const MAX_THROTTLE_ENTRIES = 500;
const recentErrors = new Map<string, number>();

function cleanupThrottleMap() {
  if (recentErrors.size <= MAX_THROTTLE_ENTRIES) return;
  const now = Date.now();
  for (const [key, ts] of recentErrors) {
    if (now - ts > SERVER_COOLDOWN_MS) {
      recentErrors.delete(key);
    }
  }
  // 정리 후에도 초과하면 전체 초기화
  if (recentErrors.size > MAX_THROTTLE_ENTRIES) {
    recentErrors.clear();
  }
}

function isThrottled(report: ErrorReport): boolean {
  const key = `${report.errorType}::${report.message}`;
  const now = Date.now();
  const last = recentErrors.get(key);

  if (last && now - last < SERVER_COOLDOWN_MS) {
    return true;
  }

  cleanupThrottleMap();
  recentErrors.set(key, now);
  return false;
}

function getErrorLabel(type: string): string {
  return type === 'ERROR_BOUNDARY'
    ? 'Error Boundary (컴포넌트 크래시)'
    : 'ChunkLoadError (JS 로딩 실패)';
}

function buildSlackPayload(report: ErrorReport) {
  const blocks: Record<string, unknown>[] = [
    {
      type: 'header',
      text: { type: 'plain_text', text: '🔴 Frontend Error', emoji: true },
    },
    {
      type: 'section',
      fields: [
        { type: 'mrkdwn', text: `*Type:*\n${getErrorLabel(report.errorType)}` },
        { type: 'mrkdwn', text: `*Time:*\n${report.timestamp}` },
      ],
    },
    {
      type: 'section',
      fields: [
        { type: 'mrkdwn', text: `*Page:*\n${report.pageUrl}` },
        ...(report.digest
          ? [{ type: 'mrkdwn', text: `*Digest:*\n${report.digest}` }]
          : []),
      ],
    },
    {
      type: 'section',
      text: {
        type: 'mrkdwn',
        text: `*Error:*\n\`\`\`${report.message.slice(0, 300)}\`\`\``,
      },
    },
  ];

  if (report.stack) {
    blocks.push({
      type: 'section',
      text: {
        type: 'mrkdwn',
        text: `*Stack:*\n\`\`\`${report.stack.slice(0, 300)}\`\`\``,
      },
    });
  }

  if (report.userAgent) {
    blocks.push({
      type: 'context',
      elements: [
        { type: 'mrkdwn', text: `UA: ${report.userAgent.slice(0, 150)}` },
      ],
    });
  }

  return { blocks };
}

export async function POST(request: NextRequest) {
  try {
    const body = await request.json();

    // 입력 검증
    if (
      !body.errorType ||
      !VALID_TYPES.has(body.errorType) ||
      !body.message ||
      !body.pageUrl ||
      !body.timestamp
    ) {
      return NextResponse.json(
        { error: 'Invalid error report' },
        { status: 400 }
      );
    }

    const report: ErrorReport = {
      errorType: body.errorType,
      message: String(body.message).slice(0, 1000),
      pageUrl: String(body.pageUrl).slice(0, 500),
      timestamp: String(body.timestamp),
      digest: body.digest ? String(body.digest).slice(0, 100) : undefined,
      stack: body.stack ? String(body.stack).slice(0, 500) : undefined,
      userAgent: body.userAgent
        ? String(body.userAgent).slice(0, 300)
        : undefined,
    };

    // 서버 측 스로틀링
    if (isThrottled(report)) {
      return NextResponse.json({ status: 'throttled' });
    }

    // Webhook URL 확인
    const webhookUrl = process.env.SLACK_FRONTEND_WEBHOOK_URL;
    if (!webhookUrl) {
      console.warn('[error-report] SLACK_FRONTEND_WEBHOOK_URL not configured');
      return NextResponse.json({ status: 'skipped' });
    }

    // Slack 전송
    const slackRes = await fetch(webhookUrl, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(buildSlackPayload(report)),
    });

    if (!slackRes.ok) {
      console.error('[error-report] Slack webhook failed:', slackRes.status);
      return NextResponse.json(
        { status: 'slack_error' },
        { status: 502 }
      );
    }

    return NextResponse.json({ status: 'sent' });
  } catch (err) {
    console.error('[error-report] Unexpected error:', err);
    return NextResponse.json(
      { error: 'Internal server error' },
      { status: 500 }
    );
  }
}
