"use server"

import { revalidatePath } from "next/cache"
import { prisma } from "@/lib/prisma"
import { requireAdmin, auth } from "@/lib/auth"
import { parseHSKJson } from "@/lib/import/hsk-json-parser"
import { parseCSV } from "@/lib/import/csv-parser"
import type { ParsedHanzi, ImportResult } from "@/lib/import/types"
import { UserRole } from "@prisma/client"
import { z } from "zod"

/**
 * Standard action result type
 */
export type ActionResult<T = void> = {
  success: boolean
  data?: T
  message?: string
  errors?: Record<string, string[]>
}

// ============================================================================
// VALIDATION SCHEMAS
// ============================================================================

const createGlobalCollectionSchema = z.object({
  name: z.string().min(1, "Name is required").max(100),
  description: z.string().optional(),
  hskLevel: z.string().optional(),
})

const importHanziSchema = z.object({
  fileData: z.string().min(1, "File data is required"),
  format: z.enum(["json", "csv"]),
  updateExisting: z.boolean().default(true),
})

const updateUserRoleSchema = z.object({
  userId: z.string().min(1),
  role: z.nativeEnum(UserRole),
})

const toggleUserStatusSchema = z.object({
  userId: z.string().min(1),
})

const initializeDatabaseSchema = z.object({
  fileNames: z.array(z.string()).min(1, "At least one file is required"),
  cleanData: z.boolean().default(false),
})

// ============================================================================
// GLOBAL COLLECTIONS
// ============================================================================

/**
 * Create a global HSK collection (admin only)
 */
export async function createGlobalCollection(
  name: string,
  description?: string,
  hskLevel?: string
): Promise<ActionResult<{ id: string }>> {
  try {
    await requireAdmin()

    const validation = createGlobalCollectionSchema.safeParse({
      name,
      description,
      hskLevel,
    })

    if (!validation.success) {
      return {
        success: false,
        message: "Validation failed",
        errors: validation.error.flatten().fieldErrors,
      }
    }

    const collection = await prisma.collection.create({
      data: {
        name,
        description,
        isGlobal: true,
        isPublic: true,
        createdBy: null,
      },
    })

    revalidatePath("/admin/collections")
    revalidatePath("/collections")

    return {
      success: true,
      data: { id: collection.id },
      message: "Global collection created successfully",
    }
  } catch (error) {
    if (error instanceof Error && error.message.startsWith("Unauthorized")) {
      return {
        success: false,
        message: error.message,
      }
    }

    return {
      success: false,
      message: "Failed to create global collection",
    }
  }
}

// ============================================================================
// HANZI IMPORT
// ============================================================================

/**
 * Import hanzi from JSON or CSV format (admin only)
 */
export async function importHanzi(
  fileData: string,
  format: "json" | "csv",
  updateExisting: boolean = true
): Promise<ActionResult<ImportResult>> {
  try {
    await requireAdmin()

    const validation = importHanziSchema.safeParse({ fileData, format, updateExisting })

    if (!validation.success) {
      return {
        success: false,
        message: "Validation failed",
        errors: validation.error.flatten().fieldErrors,
      }
    }

    // Parse the file
    const { result: parseResult, data: parsedData } = format === "json"
      ? parseHSKJson(fileData)
      : parseCSV(fileData)

    if (!parseResult.success) {
      return {
        success: false,
        data: parseResult,
        message: `Import failed: ${parseResult.errors.length} errors found`,
      }
    }

    // Save to database
    await saveParsedHanzi(parsedData, updateExisting)

    revalidatePath("/admin/hanzi")
    revalidatePath("/hanzi")

    return {
      success: true,
      data: parseResult,
      message: `Successfully imported ${parseResult.imported} hanzi`,
    }
  } catch (error) {
    if (error instanceof Error && error.message.startsWith("Unauthorized")) {
      return {
        success: false,
        message: error.message,
      }
    }

    return {
      success: false,
      message: "Failed to import hanzi",
    }
  }
}

/**
 * Save parsed hanzi to database
 */
async function saveParsedHanzi(parsedHanzi: ParsedHanzi[], updateExisting: boolean = true): Promise<void> {
  // 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,
      },
    })
  }

  for (const hanzi of parsedHanzi) {
    // Check if hanzi exists
    const existingHanzi = await prisma.hanzi.findUnique({
      where: { simplified: hanzi.simplified },
    })

    // Skip if exists and updateExisting is false
    if (existingHanzi && !updateExisting) {
      continue
    }

    // Upsert hanzi
    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 to replace it
    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, and classifiers
    for (const form of hanzi.forms) {
      const formRecord = await prisma.hanziForm.create({
        data: {
          hanziId: hanziRecord.id,
          traditional: form.traditional,
          isDefault: form.isDefault,
        },
      })

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

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

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

// ============================================================================
// IMPORT HISTORY
// ============================================================================

/**
 * Get import history (admin only)
 * Note: This is a placeholder - we don't have an import history table yet
 */
export async function getImportHistory(): Promise<
  ActionResult<{ imports: any[] }>
> {
  try {
    await requireAdmin()

    // TODO: Implement import history tracking
    // For now, return empty array

    return {
      success: true,
      data: { imports: [] },
    }
  } catch (error) {
    if (error instanceof Error && error.message.startsWith("Unauthorized")) {
      return {
        success: false,
        message: error.message,
      }
    }

    return {
      success: false,
      message: "Failed to get import history",
    }
  }
}

// ============================================================================
// USER MANAGEMENT
// ============================================================================

/**
 * Get users for management (admin only)
 */
export async function getUserManagement(
  page: number = 1,
  pageSize: number = 20
): Promise<
  ActionResult<{
    users: Array<{
      id: string
      email: string
      name: string | null
      role: UserRole
      isActive: boolean
      createdAt: Date
    }>
    total: number
    page: number
    pageSize: number
  }>
> {
  try {
    await requireAdmin()

    const skip = (page - 1) * pageSize

    const [users, total] = await Promise.all([
      prisma.user.findMany({
        select: {
          id: true,
          email: true,
          name: true,
          role: true,
          isActive: true,
          createdAt: true,
        },
        orderBy: { createdAt: "desc" },
        skip,
        take: pageSize,
      }),
      prisma.user.count(),
    ])

    return {
      success: true,
      data: {
        users,
        total,
        page,
        pageSize,
      },
    }
  } catch (error) {
    if (error instanceof Error && error.message.startsWith("Unauthorized")) {
      return {
        success: false,
        message: error.message,
      }
    }

    return {
      success: false,
      message: "Failed to get users",
    }
  }
}

/**
 * Update user role (admin only)
 */
export async function updateUserRole(
  userId: string,
  role: UserRole
): Promise<ActionResult> {
  try {
    await requireAdmin()

    const validation = updateUserRoleSchema.safeParse({ userId, role })

    if (!validation.success) {
      return {
        success: false,
        message: "Validation failed",
        errors: validation.error.flatten().fieldErrors,
      }
    }

    // Prevent changing own role
    const session = await auth()
    if (session?.user && (session.user as any).id === userId) {
      return {
        success: false,
        message: "Cannot change your own role",
      }
    }

    await prisma.user.update({
      where: { id: userId },
      data: { role },
    })

    revalidatePath("/admin/users")

    return {
      success: true,
      message: "User role updated successfully",
    }
  } catch (error) {
    if (error instanceof Error && error.message.startsWith("Unauthorized")) {
      return {
        success: false,
        message: error.message,
      }
    }

    return {
      success: false,
      message: "Failed to update user role",
    }
  }
}

/**
 * Toggle user active status (admin only)
 */
export async function toggleUserStatus(userId: string): Promise<ActionResult> {
  try {
    await requireAdmin()

    const validation = toggleUserStatusSchema.safeParse({ userId })

    if (!validation.success) {
      return {
        success: false,
        message: "Validation failed",
        errors: validation.error.flatten().fieldErrors,
      }
    }

    // Prevent deactivating own account
    const session = await auth()
    if (session?.user && (session.user as any).id === userId) {
      return {
        success: false,
        message: "Cannot deactivate your own account",
      }
    }

    const user = await prisma.user.findUnique({
      where: { id: userId },
      select: { isActive: true },
    })

    if (!user) {
      return {
        success: false,
        message: "User not found",
      }
    }

    await prisma.user.update({
      where: { id: userId },
      data: { isActive: !user.isActive },
    })

    revalidatePath("/admin/users")

    return {
      success: true,
      message: `User ${user.isActive ? "deactivated" : "activated"} successfully`,
    }
  } catch (error) {
    if (error instanceof Error && error.message.startsWith("Unauthorized")) {
      return {
        success: false,
        message: error.message,
      }
    }

    return {
      success: false,
      message: "Failed to toggle user status",
    }
  }
}

// ============================================================================
// DATABASE INITIALIZATION
// ============================================================================

/**
 * Get list of available initialization files
 */
export async function getInitializationFiles(): Promise<ActionResult<string[]>> {
  try {
    await requireAdmin()

    const fs = await import("fs/promises")
    const path = await import("path")
    const dirPath = path.join(process.cwd(), "data", "initialization")

    try {
      const files = await fs.readdir(dirPath)
      // Filter for JSON files only
      const jsonFiles = files.filter(file => file.endsWith(".json"))

      return {
        success: true,
        data: jsonFiles,
      }
    } catch (error) {
      return {
        success: false,
        message: "Initialization directory not found",
        data: [],
      }
    }
  } catch (error) {
    if (error instanceof Error && error.message.startsWith("Unauthorized")) {
      return {
        success: false,
        message: error.message,
      }
    }

    return {
      success: false,
      message: "Failed to get initialization files",
    }
  }
}

/**
 * Initialize database with hanzi and collections from a JSON file
 *
 * NOTE: This is kept for backwards compatibility but the API route
 * /api/admin/initialize should be used for real-time progress updates
 *
 * This function:
 * 1. Optionally cleans all hanzi and collections
 * 2. Imports hanzi from the specified file
 * 3. Creates collections for each unique HSK level found
 * 4. Adds hanzi to their corresponding level collections
 *
 * @param fileName - Name of the file in data/initialization/ (e.g., "complete.json")
 * @param cleanData - If true, deletes all hanzi and collections before import
 * @returns ActionResult with import statistics
 */
export async function initializeDatabase(
  fileName: string,
  cleanData: boolean = false
): Promise<ActionResult<{
  imported: number
  collectionsCreated: number
  hanziAddedToCollections: number
}>> {
  try {
    await requireAdmin()

    const validation = initializeDatabaseSchema.safeParse({ fileName, cleanData })

    if (!validation.success) {
      return {
        success: false,
        message: "Validation failed",
        errors: validation.error.flatten().fieldErrors,
      }
    }

    // Read file from filesystem
    const fs = await import("fs/promises")
    const path = await import("path")
    const filePath = path.join(process.cwd(), "data", "initialization", fileName)

    let fileData: string
    try {
      fileData = await fs.readFile(filePath, "utf-8")
    } catch (error) {
      return {
        success: false,
        message: `Failed to read file: ${fileName}`,
      }
    }

    // Parse the JSON file
    const { result: parseResult, data: parsedData } = parseHSKJson(fileData)

    if (!parseResult.success) {
      return {
        success: false,
        message: `Parse failed: ${parseResult.errors.length} errors found`,
      }
    }

    // Clean data if requested
    if (cleanData) {
      // Delete all collection items first (foreign key constraint)
      await prisma.collectionItem.deleteMany({})
      // Delete all collections
      await prisma.collection.deleteMany({})
      // Delete all user hanzi progress
      await prisma.userHanziProgress.deleteMany({})
      // Delete all session reviews
      await prisma.sessionReview.deleteMany({})
      // Delete all learning sessions
      await prisma.learningSession.deleteMany({})

      // Delete all hanzi-related data
      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({})
    }

    // Import hanzi
    await saveParsedHanzi(parsedData, true)

    // Extract all unique HSK levels from the parsed data
    const uniqueLevels = new Set<string>()
    parsedData.forEach(hanzi => {
      hanzi.hskLevels.forEach(level => {
        uniqueLevels.add(level)
      })
    })

    // Create collections for each level (if they don't exist)
    const levelCollections = new Map<string, string>() // level -> collectionId
    let collectionsCreated = 0

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

      if (existingCollection) {
        levelCollections.set(level, existingCollection.id)
      } else {
        // Create new collection
        const session = await auth()
        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++
      }
    }

    // Add hanzi to their corresponding collections
    let hanziAddedToCollections = 0

    for (const hanzi of parsedData) {
      // Find the hanzi record in the database
      const hanziRecord = await prisma.hanzi.findUnique({
        where: { simplified: hanzi.simplified },
      })

      if (!hanziRecord) continue

      // Add to each level collection
      for (const level of hanzi.hskLevels) {
        const collectionId = levelCollections.get(level)
        if (!collectionId) continue

        // Check if already in collection
        const existingItem = await prisma.collectionItem.findUnique({
          where: {
            collectionId_hanziId: {
              collectionId,
              hanziId: hanziRecord.id,
            },
          },
        })

        if (!existingItem) {
          // Get the next orderIndex
          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++
        }
      }
    }

    revalidatePath("/collections")
    revalidatePath("/hanzi")

    return {
      success: true,
      data: {
        imported: parseResult.imported,
        collectionsCreated,
        hanziAddedToCollections,
      },
      message: `Successfully initialized: ${parseResult.imported} hanzi imported, ${collectionsCreated} collections created, ${hanziAddedToCollections} hanzi added to collections`,
    }
  } catch (error) {
    if (error instanceof Error && error.message.startsWith("Unauthorized")) {
      return {
        success: false,
        message: error.message,
      }
    }

    console.error("Database initialization error:", error)
    return {
      success: false,
      message: "Failed to initialize database",
    }
  }
}
