/**
 * AI 请求构造
 *
 * 职责：
 * - 构造 AI 聊天消息
 * - 发送 AI 请求（试卷解析、结构拆分、题目详情、源文本校验、题目重写）
 * - 依赖 parse.ts 中的 schema、parseAiResponse 与 buildQuestionContent
 */

import { z } from "zod"
import { createAiChatCompletion, getAiErrorMessage } from "@/shared/lib/ai"
import { env } from "@/env.mjs"

import {
  AI_EXAM_SOURCE_VALIDATION_SYSTEM_PROMPT,
  AI_EXAM_STRUCTURE_SYSTEM_PROMPT,
  AI_EXAM_SYSTEM_PROMPT,
  AI_QUESTION_DETAIL_SYSTEM_PROMPT,
  AI_REWRITE_QUESTION_SYSTEM_PROMPT,
  AiExamResponseSchema,
  AiQuestionSchema,
  AiSourceValidationSchema,
  AiStructureResponseSchema,
  buildQuestionContent,
  parseAiResponse,
} from "./parse"

// ---------------------------------------------------------------------------
// Shared types
// ---------------------------------------------------------------------------

type AiChatMessage = { role: "system" | "user"; content: string }

type AiDraftResult =
  | { ok: true; data: z.infer<typeof AiExamResponseSchema>; rawOutput: string }
  | { ok: false; message: string }

type AiStructureDraftResult =
  | { ok: true; data: z.infer<typeof AiStructureResponseSchema>; rawOutput: string }
  | { ok: false; message: string }

export type SplitQuestionItem = {
  sectionIndex: number | null
  sectionTitle?: string
  text: string
  score?: number
}

// ---------------------------------------------------------------------------
// Message builders
// ---------------------------------------------------------------------------

const buildAiMessages = (input: {
  title?: string
  subject?: string
  grade?: string
  difficulty?: number
  totalScore?: number
  durationMin?: number
  questionCount?: number
  sourceText: string
}): AiChatMessage[] => {
  const userLines = [
    input.title ? `Title: ${input.title}` : "",
    input.subject ? `Subject: ${input.subject}` : "",
    input.grade ? `Grade: ${input.grade}` : "",
    typeof input.difficulty === "number" ? `Difficulty: ${input.difficulty}` : "",
    typeof input.totalScore === "number" ? `Total Score: ${input.totalScore}` : "",
    typeof input.durationMin === "number" ? `Duration (min): ${input.durationMin}` : "",
    input.questionCount ? `Question Count: ${input.questionCount}` : "",
    `Source Exam Text:\n${input.sourceText}`,
  ]
  const userContent = userLines.filter((l) => l.length > 0).join("\n")
  return [
    { role: "system" as const, content: AI_EXAM_SYSTEM_PROMPT },
    { role: "user" as const, content: userContent },
  ]
}

// ---------------------------------------------------------------------------
// AI request functions
// ---------------------------------------------------------------------------

export const requestAiExamDraft = async (input: {
  title?: string
  subject?: string
  grade?: string
  difficulty?: number
  totalScore?: number
  durationMin?: number
  questionCount?: number
  sourceText: string
  aiProviderId?: string
}): Promise<AiDraftResult> => {
  try {
    const aiResult = await createAiChatCompletion({
      model: String(env.AI_MODEL ?? "gpt-4o-mini"),
      providerId: input.aiProviderId,
      messages: buildAiMessages(input),
      temperature: 0.7,
      maxTokens: 4000,
    })
    const rawOutput = aiResult.content
    const data = await parseAiResponse(rawOutput, input.aiProviderId)
    const validated = AiExamResponseSchema.safeParse(data)
    if (!validated.success) {
      return { ok: false, message: "AI response format invalid" }
    }
    return { ok: true, data: validated.data, rawOutput }
  } catch (error) {
    return { ok: false, message: getAiErrorMessage(error) }
  }
}

export const requestAiExamStructureDraft = async (input: {
  title?: string
  subject?: string
  grade?: string
  difficulty?: number
  totalScore?: number
  durationMin?: number
  questionCount?: number
  sourceText: string
  aiProviderId?: string
}): Promise<AiStructureDraftResult> => {
  try {
    const aiResult = await createAiChatCompletion({
      model: String(env.AI_MODEL ?? "gpt-4o-mini"),
      providerId: input.aiProviderId,
      messages: [
        { role: "system" as const, content: AI_EXAM_STRUCTURE_SYSTEM_PROMPT },
        { role: "user" as const, content: buildAiMessages(input)[1].content },
      ],
      temperature: 0.2,
      maxTokens: 4000,
    })
    const rawOutput = aiResult.content
    const data = await parseAiResponse(rawOutput, input.aiProviderId)
    const validated = AiStructureResponseSchema.safeParse(data)
    if (!validated.success) {
      return { ok: false, message: "AI response format invalid" }
    }
    return { ok: true, data: validated.data, rawOutput }
  } catch (error) {
    return { ok: false, message: getAiErrorMessage(error) }
  }
}

export const validateExamSourceText = async (input: { sourceText: string; aiProviderId?: string }) => {
  const text = input.sourceText.trim()
  if (!text) {
    return { ok: false as const, message: "Source text is required" }
  }
  const userContent = [
    "Judge whether the following text is readable and resembles normal exam/question content (not garbled, random characters, or disordered text).",
    `Text content:\n${text}`,
  ].join("\n\n")
  try {
    const aiResult = await createAiChatCompletion({
      model: String(env.AI_MODEL ?? "gpt-4o-mini"),
      providerId: input.aiProviderId,
      messages: [
        { role: "system" as const, content: AI_EXAM_SOURCE_VALIDATION_SYSTEM_PROMPT },
        { role: "user" as const, content: userContent },
      ],
      temperature: 0,
      maxTokens: 300,
    })
    const parsed = await parseAiResponse(aiResult.content, input.aiProviderId)
    const validated = AiSourceValidationSchema.safeParse(parsed)
    if (!validated.success) {
      return { ok: false as const, message: "Source text validation failed, please retry" }
    }
    if (!validated.data.valid) {
      return {
        ok: false as const,
        message: validated.data.reason?.trim() || "Text appears garbled or disordered, please paste clear and complete question content",
      }
    }
    return { ok: true as const }
  } catch (error) {
    return { ok: false as const, message: getAiErrorMessage(error) }
  }
}

export const parseQuestionDetail = async (input: {
  item: SplitQuestionItem
  subject?: string
  grade?: string
  difficulty: number
  aiProviderId?: string
}): Promise<z.infer<typeof AiQuestionSchema>> => {
  const normalizeQuestionCandidate = (value: unknown): unknown => {
    if (!value || typeof value !== "object") return value
    // 从 unknown 收窄为 Record<string, unknown> 以进行字段检查
    const record = value as Record<string, unknown>
    const contentRaw = record.content
    if (!contentRaw || typeof contentRaw !== "object") return value
    const content = contentRaw as Record<string, unknown>
    const normalizedSubQuestions = Array.isArray(content.subQuestions)
      ? content.subQuestions
      : Array.isArray(content.subquestions)
        ? content.subquestions
        : Array.isArray(content.sub_questions)
          ? content.sub_questions
          : undefined
    if (!normalizedSubQuestions) return value
    return {
      ...record,
      content: {
        ...content,
        subQuestions: normalizedSubQuestions,
      },
    }
  }

  const userContent = [
    input.subject ? `Subject: ${input.subject}` : "",
    input.grade ? `Grade: ${input.grade}` : "",
    `Question Text:\n${input.item.text}`,
  ].filter((line) => line.length > 0).join("\n\n")

  try {
    const aiResult = await createAiChatCompletion({
      model: String(env.AI_MODEL ?? "gpt-4o-mini"),
      providerId: input.aiProviderId,
      messages: [
        { role: "system" as const, content: AI_QUESTION_DETAIL_SYSTEM_PROMPT },
        { role: "user" as const, content: userContent },
      ],
      temperature: 0.4,
      maxTokens: 1200,
    })
    const parsed = await parseAiResponse(aiResult.content, input.aiProviderId)
    const candidate = parsed && typeof parsed === "object" && "question" in parsed
      ? (parsed as { question: unknown }).question
      : parsed
    const validated = AiQuestionSchema.safeParse(normalizeQuestionCandidate(candidate))
    if (validated.success) {
      const q = validated.data
      return {
        type: q.type,
        difficulty: q.difficulty ?? input.difficulty,
        score: q.score ?? input.item.score ?? 0,
        content: q.content,
      } satisfies z.infer<typeof AiQuestionSchema>
    }
  } catch (error) {
    console.warn("[parseQuestionDetail] Falling back to text question:", error instanceof Error ? error.message : String(error))
  }

  return {
    type: "text",
    difficulty: input.difficulty,
    score: input.item.score ?? 0,
    content: { text: input.item.text },
  } satisfies z.infer<typeof AiQuestionSchema>
}

export const regenerateAiQuestionByInstruction = async (input: {
  instruction: string
  originalQuestion: z.infer<typeof AiQuestionSchema>
  sourceText?: string
  aiProviderId?: string
}) => {
  const originalDifficulty = input.originalQuestion.difficulty ?? 3
  const originalScore = input.originalQuestion.score ?? 0
  const contextLines = [
    `Instruction:\n${input.instruction}`,
    `Original Question JSON:\n${JSON.stringify(input.originalQuestion, null, 2)}`,
    input.sourceText ? `Source Exam Text:\n${input.sourceText}` : "",
  ]
  const userContent = contextLines.filter((line) => line.length > 0).join("\n\n")
  try {
    const aiResult = await createAiChatCompletion({
      model: String(env.AI_MODEL ?? "gpt-4o-mini"),
      providerId: input.aiProviderId && input.aiProviderId.length > 0 ? input.aiProviderId : undefined,
      messages: [
        { role: "system" as const, content: AI_REWRITE_QUESTION_SYSTEM_PROMPT },
        { role: "user" as const, content: userContent },
      ],
      temperature: 0.7,
      maxTokens: 2000,
    })
    const parsed = await parseAiResponse(aiResult.content, input.aiProviderId)
    const candidate = parsed && typeof parsed === "object" && "question" in parsed
      ? (parsed as { question: unknown }).question
      : parsed
    const validated = AiQuestionSchema.safeParse(candidate)
    if (!validated.success) {
      return { ok: false as const, message: "AI question format invalid" }
    }
    const question = validated.data
    return {
      ok: true as const,
      data: {
        type: question.type,
        difficulty: question.difficulty ?? originalDifficulty,
        score: question.score ?? originalScore,
        content: buildQuestionContent(question),
      },
    }
  } catch (error) {
    return { ok: false as const, message: getAiErrorMessage(error) }
  }
}
