import { NextResponse } from "next/server"

import { auth } from "@/auth"
import { Permissions } from "@/shared/types/permissions"
import { requirePermission, PermissionDeniedError } from "@/shared/lib/auth-guard"
import { createAiChatCompletion, getAiErrorMessage } from "@/shared/lib/ai"
import { rateLimit, rateLimitKey, rateLimitHeaders, RATE_LIMIT_RULES } from "@/shared/lib/rate-limit"
import { trackEvent } from "@/shared/lib/track-event"
import { env } from "@/env.mjs"

import { CHAT_SYSTEM_PROMPT, SOCRATIC_TUTOR_SYSTEM_PROMPT } from "@/modules/ai/services/prompt-templates"
import {
  filterUserInput,
  filterAiOutput,
  tryConsumeDailyQuota,
  refundDailyQuota,
  validateSocraticOutput,
} from "@/modules/ai/services/content-safety"
import { AiChatInputSchema } from "@/modules/ai/schema"
import type { AiChatMessage } from "@/modules/ai/types"

export const dynamic = "force-dynamic"

const getStatusFromError = (message: string): number => {
  if (message === "Invalid payload" || message === "Messages are required") return 400
  if (message === "AI API key missing") return 500
  if (message === "Empty response") return 502
  return 502
}

/**
 * AI 聊天非流式端点
 *
 * 安全策略（与流式端点 /api/ai/chat/stream 一致）：
 * - requirePermission(AI_CHAT) 权限校验
 * - rateLimit 每分钟限流（防高频滥用）
 * - Zod 校验输入（AiChatInputSchema，限制消息数/长度）
 * - tryConsumeDailyQuota 原子化每日限额（防 TOCTOU 竞态）
 * - 输入/输出内容安全过滤
 * - 学生侧 Socratic 模式（服务端强制，忽略客户端 systemPrompt）
 * - 过滤/失败时 refundDailyQuota（不惩罚用户）
 * - trackEvent 使用量埋点
 */
export async function POST(req: Request): Promise<NextResponse> {
  const startTime = Date.now()

  try {
    // 1. 权限校验
    const ctx = await requirePermission(Permissions.AI_CHAT)
    const userId = ctx.userId
    const session = await auth()
    const userRole = session?.user?.role ?? "student"
    const isStudent = userRole === "student"

    // 2. Rate limit
    const limitKey = rateLimitKey("ai-chat", userId)
    const limit = await rateLimit({ key: limitKey, ...RATE_LIMIT_RULES.AI_CHAT })
    if (!limit.success) {
      return NextResponse.json(
        { success: false, message: "Rate limit exceeded. Please slow down." },
        { status: 429, headers: rateLimitHeaders(limit) }
      )
    }

    // 3. Zod 校验输入（防止超大 message 导致 token 爆炸）
    const rawBody = await req.json().catch(() => null)
    const parseResult = AiChatInputSchema.safeParse(rawBody)
    if (!parseResult.success) {
      return NextResponse.json(
        { success: false, message: "Invalid input" },
        { status: 400, headers: rateLimitHeaders(limit) }
      )
    }
    const body = parseResult.data

    // 4. 原子化每日限额检查（防 TOCTOU 竞态）
    const quotaResult = tryConsumeDailyQuota(userId, userRole)
    if (quotaResult.blocked) {
      return NextResponse.json(
        { success: false, message: "Daily AI usage limit reached. Please try again tomorrow." },
        { status: 429, headers: rateLimitHeaders(limit) }
      )
    }

    // 5. 输入安全过滤
    for (const msg of body.messages) {
      if (msg.role === "user") {
        const filterResult = filterUserInput(msg.content, { isStudent })
        if (filterResult.blocked) {
          // 输入被过滤，回退配额
          refundDailyQuota(userId)
          return NextResponse.json(
            { success: false, message: "Input blocked by safety filter." },
            { status: 400, headers: rateLimitHeaders(limit) }
          )
        }
      }
    }

    // 6. 构建 system prompt
    //    安全：服务端强制使用系统提示词，忽略客户端传入的 systemPrompt，
    //    防止学生绕过 Socratic 模式获取直接答案。
    const baseSystemPrompt = isStudent
      ? SOCRATIC_TUTOR_SYSTEM_PROMPT
      : CHAT_SYSTEM_PROMPT

    const messages: AiChatMessage[] = [
      { role: "system", content: baseSystemPrompt },
      ...body.messages,
    ]

    // 7. 调用 AI
    const result = await createAiChatCompletion({
      messages: messages.map((m) => ({ role: m.role, content: m.content })),
      model: String(env.AI_MODEL ?? "gpt-4o-mini"),
      temperature: 0.7,
      ...(body.providerId ? { providerId: body.providerId } : {}),
    })

    // 8. 输出安全过滤
    const outputFilter = filterAiOutput(result.content, { isStudent })
    if (outputFilter.blocked) {
      // 输出被过滤，回退配额
      refundDailyQuota(userId)
      return NextResponse.json(
        { success: false, message: "Content filtered for safety." },
        { status: 400, headers: rateLimitHeaders(limit) }
      )
    }

    // 9. 学生侧：苏格拉底式辅导输出校验
    if (isStudent && result.content) {
      const socraticResult = validateSocraticOutput(result.content)
      if (!socraticResult.valid) {
        // 不阻断，但记录警告
        void trackEvent({
          event: "ai.chat",
          userId,
          targetType: "chat",
          properties: {
            success: true,
            durationMs: Date.now() - startTime,
            socraticWarning: true,
          },
        }).catch(() => {
          // 静默失败
        })
      }
    }

    // 10. 埋点：非流式聊天成功
    void trackEvent({
      event: "ai.chat",
      userId,
      targetType: "chat",
      properties: {
        success: true,
        durationMs: Date.now() - startTime,
        tokenCount: result.content.length / 4,
        isStudent,
      },
    }).catch(() => {
      // 静默失败
    })

    return NextResponse.json(
      { success: true, content: result.content, usage: result.usage },
      { headers: rateLimitHeaders(limit) }
    )
  } catch (e) {
    const errorMessage = e instanceof Error ? e.message : String(e)

    if (e instanceof PermissionDeniedError) {
      return NextResponse.json(
        { success: false, message: e.message },
        { status: 403 }
      )
    }
    const message = getAiErrorMessage(e)

    // 埋点：非流式聊天失败
    void trackEvent({
      event: "ai.chat",
      targetType: "chat",
      properties: {
        success: false,
        durationMs: Date.now() - startTime,
        errorMessage,
      },
    }).catch(() => {
      // 静默失败
    })

    return NextResponse.json({ success: false, message }, { status: getStatusFromError(message) })
  }
}
