import { z } from "zod"
import type {
  HSKJsonEntry,
  HSKJsonForm,
  ParsedHanzi,
  ParsedHanziForm,
  ImportResult,
  ImportError,
} from "./types"

/**
 * Zod schema for HSK JSON validation
 */
const HSKJsonFormSchema = z.object({
  traditional: z.string().min(1),
  transcriptions: z.object({
    pinyin: z.string().min(1),
    numeric: z.string().optional(),
    wadegiles: z.string().optional(),
  }).catchall(z.string().optional()),
  meanings: z.array(z.string().min(1)).min(1),
  classifiers: z.array(z.string()).optional(),
})

const HSKJsonEntrySchema = z.object({
  simplified: z.string().min(1),
  radical: z.string().optional(),
  level: z.array(z.string()).optional(),
  frequency: z.number().int().positive().optional(),
  pos: z.array(z.string()).optional(),
  forms: z.array(HSKJsonFormSchema).min(1),
})

/**
 * Parse HSK JSON format
 * Source: https://github.com/drkameleon/complete-hsk-vocabulary
 */
export function parseHSKJson(jsonString: string): {
  result: ImportResult
  data: ParsedHanzi[]
} {
  const errors: ImportError[] = []
  const parsed: ParsedHanzi[] = []
  let entries: unknown[]

  // Parse JSON
  try {
    const data = JSON.parse(jsonString)
    entries = Array.isArray(data) ? data : [data]
  } catch (error) {
    return {
      result: {
        success: false,
        imported: 0,
        failed: 0,
        errors: [{ error: `Invalid JSON: ${error instanceof Error ? error.message : "Unknown error"}` }],
      },
      data: [],
    }
  }

  // Validate and transform each entry
  for (let i = 0; i < entries.length; i++) {
    try {
      const entry = HSKJsonEntrySchema.parse(entries[i])
      const parsedEntry = transformHSKJsonEntry(entry)
      parsed.push(parsedEntry)
    } catch (error) {
      const simplified = (entries[i] as any)?.simplified || "unknown"
      const errorMessage = error instanceof z.ZodError
        ? error.errors.map(e => `${e.path.join(".")}: ${e.message}`).join(", ")
        : error instanceof Error
        ? error.message
        : "Unknown error"

      errors.push({
        line: i + 1,
        character: simplified,
        error: errorMessage,
      })
    }
  }

  return {
    result: {
      success: errors.length === 0,
      imported: parsed.length,
      failed: errors.length,
      errors,
    },
    data: parsed,
  }
}

/**
 * Transform HSK JSON entry to ParsedHanzi format
 */
function transformHSKJsonEntry(entry: HSKJsonEntry): ParsedHanzi {
  return {
    simplified: entry.simplified,
    radical: entry.radical,
    frequency: entry.frequency,
    hskLevels: entry.level || [],
    partsOfSpeech: entry.pos || [],
    forms: entry.forms.map((form, index) => transformHSKJsonForm(form, index === 0)),
  }
}

/**
 * Transform HSK JSON form to ParsedHanziForm format
 */
function transformHSKJsonForm(form: HSKJsonForm, isDefault: boolean): ParsedHanziForm {
  // Extract transcriptions
  const transcriptions = Object.entries(form.transcriptions)
    .filter(([_, value]) => value !== undefined)
    .map(([type, value]) => ({
      type,
      value: value!,
    }))

  // Parse meanings (can be semicolon-separated or array)
  const meanings = form.meanings.flatMap((meaningStr, index) =>
    meaningStr.split(";").map((m, subIndex) => ({
      languageCode: "en", // Default to English
      meaning: m.trim(),
      orderIndex: index * 100 + subIndex,
    }))
  )

  return {
    traditional: form.traditional,
    isDefault,
    transcriptions,
    meanings,
    classifiers: form.classifiers || [],
  }
}

/**
 * Validate a single HSK JSON entry
 */
export function validateHSKJsonEntry(entry: unknown): {
  valid: boolean
  errors: string[]
} {
  try {
    HSKJsonEntrySchema.parse(entry)
    return { valid: true, errors: [] }
  } catch (error) {
    if (error instanceof z.ZodError) {
      return {
        valid: false,
        errors: error.errors.map(e => `${e.path.join(".")}: ${e.message}`),
      }
    }
    return {
      valid: false,
      errors: [error instanceof Error ? error.message : "Unknown error"],
    }
  }
}
