import { NextRequest } from "next/server"
import { isAdminOrModerator } from "@/lib/auth"
import { auth } from "@/lib/auth"
import { prisma } from "@/lib/prisma"
import { parseHSKJson } from "@/lib/import/hsk-json-parser"
import type { ParsedHanzi } from "@/lib/import/types"

/**
 * SSE endpoint for database initialization with real-time progress updates
 *
 * POST /api/admin/initialize
 * Body: { fileNames: string[], cleanData: boolean }
 *
 * Returns Server-Sent Events stream with progress updates:
 * - progress: { percent, current, total, message }
 * - complete: { imported, collectionsCreated, hanziAddedToCollections }
 * - error: { message }
 */
export async function POST(req: NextRequest) {
  try {
    // Check admin authorization
    const isAuthorized = await isAdminOrModerator()
    if (!isAuthorized) {
      return new Response("Unauthorized", { status: 401 })
    }

    const session = await auth()

    const body = await req.json()
    const { fileNames, cleanData } = body as { fileNames: string[]; cleanData: boolean }

    if (!fileNames || fileNames.length === 0) {
      return new Response("No files specified", { status: 400 })
    }

    // Create SSE stream with proper flushing
    const encoder = new TextEncoder()
    const { readable, writable } = new TransformStream()
    const writer = writable.getWriter()

    // Start processing in background (don't await - let it run while streaming)
    const processInitialization = async () => {
      try {
        // Helper to send SSE events with immediate flush
        const sendEvent = async (event: string, data: any) => {
          const message = `event: ${event}\ndata: ${JSON.stringify(data)}\n\n`
          await writer.write(encoder.encode(message))
        }

        // Step 1: Read and parse all files
        await sendEvent("progress", { percent: 0, current: 0, total: 0, message: "Reading files..." })

        const fs = await import("fs/promises")
        const path = await import("path")
        const allParsedHanzi: ParsedHanzi[] = []
        let totalFiles = fileNames.length
        let filesProcessed = 0

        for (const fileName of fileNames) {
          const filePath = path.join(process.cwd(), "data", "initialization", fileName)

          try {
            const fileData = await fs.readFile(filePath, "utf-8")
            const { result, data } = parseHSKJson(fileData)

            if (!result.success) {
              await sendEvent("error", { message: `Failed to parse ${fileName}: ${result.errors.join(", ")}` })
              await writer.close()
              return
            }

            allParsedHanzi.push(...data)
            filesProcessed++

            await sendEvent("progress", {
              percent: Math.round((filesProcessed / totalFiles) * 10),
              current: filesProcessed,
              total: totalFiles,
              message: `Parsed ${fileName} (${data.length} hanzi)`,
            })
          } catch (error) {
            await sendEvent("error", { message: `Failed to read ${fileName}` })
            await writer.close()
            return
          }
        }

        const totalHanzi = allParsedHanzi.length
        await sendEvent("progress", {
          percent: 10,
          current: 0,
          total: totalHanzi,
          message: `Ready to import ${totalHanzi} hanzi`,
        })

        // Step 2: Clean data if requested
        if (cleanData) {
          await sendEvent("progress", { percent: 15, current: 0, total: totalHanzi, message: "Cleaning existing data..." })

          await prisma.collectionItem.deleteMany({})
          await prisma.collection.deleteMany({})
          await prisma.userHanziProgress.deleteMany({})
          await prisma.sessionReview.deleteMany({})
          await prisma.learningSession.deleteMany({})
          await prisma.hanziMeaning.deleteMany({})
          await prisma.hanziTranscription.deleteMany({})
          await prisma.hanziClassifier.deleteMany({})
          await prisma.hanziForm.deleteMany({})
          await prisma.hanziHSKLevel.deleteMany({})
          await prisma.hanziPOS.deleteMany({})
          await prisma.hanzi.deleteMany({})

          await sendEvent("progress", { percent: 20, current: 0, total: totalHanzi, message: "Data cleaned" })
        } else {
          await sendEvent("progress", { percent: 20, current: 0, total: totalHanzi, message: "Skipping clean" })
        }

        // Step 3: Get or create English language
        let englishLanguage = await prisma.language.findUnique({ where: { code: "en" } })
        if (!englishLanguage) {
          englishLanguage = await prisma.language.create({
            data: { code: "en", name: "English", nativeName: "English", isActive: true },
          })
        }

        // Step 4: Import hanzi with progress updates
        let imported = 0
        const importStartPercent = 20
        const importEndPercent = 70

        for (const hanzi of allParsedHanzi) {
          // Import hanzi (same logic as saveParsedHanzi but inline)
          const hanziRecord = await prisma.hanzi.upsert({
            where: { simplified: hanzi.simplified },
            update: { radical: hanzi.radical, frequency: hanzi.frequency },
            create: { simplified: hanzi.simplified, radical: hanzi.radical, frequency: hanzi.frequency },
          })

          // Delete existing related data
          await prisma.hanziForm.deleteMany({ where: { hanziId: hanziRecord.id } })
          await prisma.hanziHSKLevel.deleteMany({ where: { hanziId: hanziRecord.id } })
          await prisma.hanziPOS.deleteMany({ where: { hanziId: hanziRecord.id } })

          // Create HSK levels
          if (hanzi.hskLevels.length > 0) {
            await prisma.hanziHSKLevel.createMany({
              data: hanzi.hskLevels.map(level => ({ hanziId: hanziRecord.id, level })),
            })
          }

          // Create parts of speech
          if (hanzi.partsOfSpeech.length > 0) {
            await prisma.hanziPOS.createMany({
              data: hanzi.partsOfSpeech.map(pos => ({ hanziId: hanziRecord.id, pos })),
            })
          }

          // Create forms with transcriptions, meanings, classifiers
          for (const form of hanzi.forms) {
            const formRecord = await prisma.hanziForm.create({
              data: { hanziId: hanziRecord.id, traditional: form.traditional, isDefault: form.isDefault },
            })

            if (form.transcriptions.length > 0) {
              await prisma.hanziTranscription.createMany({
                data: form.transcriptions.map(trans => ({
                  formId: formRecord.id,
                  type: trans.type,
                  value: trans.value,
                })),
              })
            }

            if (form.meanings.length > 0) {
              await prisma.hanziMeaning.createMany({
                data: form.meanings.map(meaning => ({
                  formId: formRecord.id,
                  languageId: englishLanguage!.id,
                  meaning: meaning.meaning,
                })),
              })
            }

            if (form.classifiers.length > 0) {
              await prisma.hanziClassifier.createMany({
                data: form.classifiers.map(classifier => ({
                  formId: formRecord.id,
                  classifier: classifier,
                })),
              })
            }
          }

          imported++

          // Send progress update every 50 hanzi or on last one
          if (imported % 50 === 0 || imported === totalHanzi) {
            const percent = importStartPercent + Math.round(((imported / totalHanzi) * (importEndPercent - importStartPercent)))
            await sendEvent("progress", {
              percent,
              current: imported,
              total: totalHanzi,
              message: `Importing hanzi: ${imported}/${totalHanzi}`,
            })
          }
        }

        await sendEvent("progress", { percent: 70, current: totalHanzi, total: totalHanzi, message: "All hanzi imported" })

        // Step 5: Extract unique HSK levels and create collections
        await sendEvent("progress", { percent: 75, current: 0, total: 0, message: "Creating collections..." })

        const uniqueLevels = new Set<string>()
        allParsedHanzi.forEach(hanzi => {
          hanzi.hskLevels.forEach(level => uniqueLevels.add(level))
        })

        const levelCollections = new Map<string, string>()
        let collectionsCreated = 0

        for (const level of uniqueLevels) {
          const existingCollection = await prisma.collection.findFirst({
            where: { name: `HSK ${level}`, isPublic: true },
          })

          if (existingCollection) {
            levelCollections.set(level, existingCollection.id)
          } else {
            const newCollection = await prisma.collection.create({
              data: {
                name: `HSK ${level}`,
                description: `HSK ${level} vocabulary collection`,
                isPublic: true,
                createdBy: session?.user?.id,
              },
            })
            levelCollections.set(level, newCollection.id)
            collectionsCreated++
          }
        }

        await sendEvent("progress", {
          percent: 80,
          current: collectionsCreated,
          total: uniqueLevels.size,
          message: `Created ${collectionsCreated} collections`,
        })

        // Step 6: Add hanzi to collections
        await sendEvent("progress", { percent: 85, current: 0, total: totalHanzi, message: "Adding hanzi to collections..." })

        let hanziAddedToCollections = 0
        let processedForCollections = 0

        for (const hanzi of allParsedHanzi) {
          const hanziRecord = await prisma.hanzi.findUnique({ where: { simplified: hanzi.simplified } })
          if (!hanziRecord) continue

          for (const level of hanzi.hskLevels) {
            const collectionId = levelCollections.get(level)
            if (!collectionId) continue

            const existingItem = await prisma.collectionItem.findUnique({
              where: { collectionId_hanziId: { collectionId, hanziId: hanziRecord.id } },
            })

            if (!existingItem) {
              const maxOrderIndex = await prisma.collectionItem.findFirst({
                where: { collectionId },
                orderBy: { orderIndex: "desc" },
                select: { orderIndex: true },
              })

              await prisma.collectionItem.create({
                data: {
                  collectionId,
                  hanziId: hanziRecord.id,
                  orderIndex: (maxOrderIndex?.orderIndex ?? -1) + 1,
                },
              })
              hanziAddedToCollections++
            }
          }

          processedForCollections++

          // Send progress update every 100 hanzi
          if (processedForCollections % 100 === 0 || processedForCollections === totalHanzi) {
            const percent = 85 + Math.round(((processedForCollections / totalHanzi) * 15))
            await sendEvent("progress", {
              percent,
              current: processedForCollections,
              total: totalHanzi,
              message: `Adding to collections: ${processedForCollections}/${totalHanzi}`,
            })
          }
        }

        // Step 7: Complete
        await sendEvent("complete", {
          imported: totalHanzi,
          collectionsCreated,
          hanziAddedToCollections,
        })

        await writer.close()
      } catch (error) {
        console.error("Initialization error:", error)
        const message = `event: error\ndata: ${JSON.stringify({ message: "Initialization failed" })}\n\n`
        await writer.write(encoder.encode(message))
        await writer.close()
      }
    }

    // Start processing (don't await - let it stream)
    processInitialization()

    return new Response(readable, {
      headers: {
        "Content-Type": "text/event-stream",
        "Cache-Control": "no-cache, no-transform",
        "Connection": "keep-alive",
        "X-Accel-Buffering": "no", // Disable nginx buffering
      },
    })
  } catch (error) {
    console.error("API error:", error)
    return new Response("Internal server error", { status: 500 })
  }
}
