import { z } from "zod"
import type {
  CSVRow,
  ParsedHanzi,
  ImportResult,
  ImportError,
} from "./types"

/**
 * Zod schema for CSV row validation
 */
const CSVRowSchema = z.object({
  simplified: z.string().min(1),
  traditional: z.string().min(1),
  pinyin: z.string().min(1),
  meaning: z.string().min(1),
  hsk_level: z.string().optional(),
  radical: z.string().optional(),
  frequency: z.string().optional(),
  pos: z.string().optional(),
  classifiers: z.string().optional(),
})

/**
 * Parse CSV format
 * Expected format:
 * simplified,traditional,pinyin,meaning,hsk_level,radical,frequency,pos,classifiers
 */
export function parseCSV(csvString: string): {
  result: ImportResult
  data: ParsedHanzi[]
} {
  const errors: ImportError[] = []
  const parsed: ParsedHanzi[] = []
  const lines = csvString.trim().split("\n")

  if (lines.length === 0) {
    return {
      result: {
        success: false,
        imported: 0,
        failed: 0,
        errors: [{ error: "Empty CSV file" }],
      },
      data: [],
    }
  }

  // Parse header
  const headerLine = lines[0]
  const headers = parseCSVLine(headerLine)

  if (!validateHeaders(headers)) {
    return {
      result: {
        success: false,
        imported: 0,
        failed: 0,
        errors: [{
          error: `Invalid CSV headers. Expected at least: simplified,traditional,pinyin,meaning. Got: ${headers.join(",")}`,
        }],
      },
      data: [],
    }
  }

  // Parse data rows
  for (let i = 1; i < lines.length; i++) {
    const line = lines[i].trim()
    if (!line) continue // Skip empty lines

    try {
      const values = parseCSVLine(line)
      const row = parseCSVRow(headers, values)
      const validationResult = CSVRowSchema.safeParse(row)

      if (!validationResult.success) {
        throw new Error(
          validationResult.error.errors
            .map(e => `${e.path.join(".")}: ${e.message}`)
            .join(", ")
        )
      }

      const parsedEntry = transformCSVRow(validationResult.data)
      parsed.push(parsedEntry)
    } catch (error) {
      const simplified = line.split(",")[0] || "unknown"
      errors.push({
        line: i + 1,
        character: simplified,
        error: error instanceof Error ? error.message : "Unknown error",
      })
    }
  }

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

/**
 * Parse a CSV line handling quoted values
 */
function parseCSVLine(line: string): string[] {
  const values: string[] = []
  let current = ""
  let inQuotes = false

  for (let i = 0; i < line.length; i++) {
    const char = line[i]
    const nextChar = line[i + 1]

    if (char === '"') {
      if (inQuotes && nextChar === '"') {
        // Escaped quote
        current += '"'
        i++
      } else {
        // Toggle quote state
        inQuotes = !inQuotes
      }
    } else if (char === "," && !inQuotes) {
      // End of field
      values.push(current.trim())
      current = ""
    } else {
      current += char
    }
  }

  // Add last field
  values.push(current.trim())

  return values
}

/**
 * Validate CSV headers
 */
function validateHeaders(headers: string[]): boolean {
  const required = ["simplified", "traditional", "pinyin", "meaning"]
  return required.every(h => headers.includes(h))
}

/**
 * Convert CSV values array to row object
 */
function parseCSVRow(headers: string[], values: string[]): CSVRow {
  const row: any = {}
  headers.forEach((header, index) => {
    const value = values[index]?.trim()
    if (value) {
      row[header] = value
    }
  })
  return row as CSVRow
}

/**
 * Transform CSV row to ParsedHanzi format
 */
function transformCSVRow(row: CSVRow): ParsedHanzi {
  // Parse HSK levels (comma-separated)
  const hskLevels = row.hsk_level
    ? row.hsk_level.split(",").map(l => l.trim())
    : []

  // Parse parts of speech (comma-separated)
  const partsOfSpeech = row.pos
    ? row.pos.split(",").map(p => p.trim())
    : []

  // Parse frequency
  const frequency = row.frequency
    ? parseInt(row.frequency, 10)
    : undefined

  // Parse classifiers (comma-separated)
  const classifiers = row.classifiers
    ? row.classifiers.split(",").map(c => c.trim())
    : []

  // Parse meanings (semicolon-separated)
  const meanings = row.meaning.split(";").map((m, index) => ({
    languageCode: "en",
    meaning: m.trim(),
    orderIndex: index,
  }))

  return {
    simplified: row.simplified,
    radical: row.radical,
    frequency,
    hskLevels,
    partsOfSpeech,
    forms: [
      {
        traditional: row.traditional,
        isDefault: true,
        transcriptions: [
          {
            type: "pinyin",
            value: row.pinyin,
          },
        ],
        meanings,
        classifiers,
      },
    ],
  }
}

/**
 * Generate CSV template
 */
export function generateCSVTemplate(): string {
  const headers = [
    "simplified",
    "traditional",
    "pinyin",
    "meaning",
    "hsk_level",
    "radical",
    "frequency",
    "pos",
    "classifiers",
  ]

  const example = [
    "爱好",
    "愛好",
    "ài hào",
    "to like; hobby",
    "new-1,old-3",
    "爫",
    "4902",
    "n,v",
    "个",
  ]

  return [headers.join(","), example.join(",")].join("\n")
}
