import { describe, it, expect, beforeEach } from "vitest"
import { prisma } from "@/lib/prisma"
import { searchHanzi, getHanzi, getHanziBySimplified } from "./hanzi"

/**
 * Integration tests for hanzi actions
 */

describe("Hanzi Actions Integration Tests", () => {
  let englishLanguage: any
  let hanzi1: any
  let hanzi2: any
  let hanzi3: any

  beforeEach(async () => {
    // Create English language
    englishLanguage = await prisma.language.create({
      data: {
        code: "en",
        name: "English",
        nativeName: "English",
        isActive: true,
      },
    })

    // Create test hanzi with full data
    hanzi1 = await prisma.hanzi.create({
      data: { simplified: "好", radical: "女", frequency: 100 },
    })
    const form1 = await prisma.hanziForm.create({
      data: {
        hanziId: hanzi1.id,
        traditional: "好",
        isDefault: true,
      },
    })
    await prisma.hanziTranscription.createMany({
      data: [
        { formId: form1.id, type: "pinyin", value: "hǎo" },
        { formId: form1.id, type: "numeric", value: "hao3" },
      ],
    })
    await prisma.hanziMeaning.create({
      data: {
        formId: form1.id,
        languageId: englishLanguage.id,
        meaning: "good, well",
        orderIndex: 0,
      },
    })
    await prisma.hanziHSKLevel.create({
      data: { hanziId: hanzi1.id, level: "new-1" },
    })
    await prisma.hanziPOS.create({
      data: { hanziId: hanzi1.id, pos: "adj" },
    })
    await prisma.hanziClassifier.create({
      data: { formId: form1.id, classifier: "个" },
    })

    hanzi2 = await prisma.hanzi.create({
      data: { simplified: "你", radical: "人", frequency: 50 },
    })
    const form2 = await prisma.hanziForm.create({
      data: {
        hanziId: hanzi2.id,
        traditional: "你",
        isDefault: true,
      },
    })
    await prisma.hanziTranscription.create({
      data: { formId: form2.id, type: "pinyin", value: "nǐ" },
    })
    await prisma.hanziMeaning.create({
      data: {
        formId: form2.id,
        languageId: englishLanguage.id,
        meaning: "you",
        orderIndex: 0,
      },
    })
    await prisma.hanziHSKLevel.create({
      data: { hanziId: hanzi2.id, level: "new-1" },
    })

    hanzi3 = await prisma.hanzi.create({
      data: { simplified: "中国", radical: null, frequency: 300 },
    })
    const form3 = await prisma.hanziForm.create({
      data: {
        hanziId: hanzi3.id,
        traditional: "中國",
        isDefault: true,
      },
    })
    await prisma.hanziTranscription.create({
      data: { formId: form3.id, type: "pinyin", value: "zhōng guó" },
    })
    await prisma.hanziMeaning.create({
      data: {
        formId: form3.id,
        languageId: englishLanguage.id,
        meaning: "China",
        orderIndex: 0,
      },
    })
    await prisma.hanziHSKLevel.create({
      data: { hanziId: hanzi3.id, level: "new-2" },
    })
  })

  describe("searchHanzi", () => {
    it("should search by simplified character", async () => {
      const result = await searchHanzi("好", undefined, 20, 0)

      expect(result.success).toBe(true)
      expect(result.data?.hanzi.length).toBeGreaterThan(0)
      expect(result.data?.hanzi.some((h) => h.simplified === "好")).toBe(true)
      expect(result.data?.total).toBeGreaterThan(0)
    })

    it("should search by pinyin", async () => {
      const result = await searchHanzi("hǎo", undefined, 20, 0)

      expect(result.success).toBe(true)
      expect(result.data?.hanzi.length).toBeGreaterThan(0)
      expect(result.data?.hanzi.some((h) => h.pinyin?.includes("hǎo"))).toBe(true)
    })

    it("should search by meaning", async () => {
      const result = await searchHanzi("good", undefined, 20, 0)

      expect(result.success).toBe(true)
      expect(result.data?.hanzi.length).toBeGreaterThan(0)
      expect(result.data?.hanzi.some((h) => h.meaning?.includes("good"))).toBe(true)
    })

    it("should filter by HSK level", async () => {
      const result = await searchHanzi("好", "new-1", 20, 0)

      expect(result.success).toBe(true)
      expect(result.data?.hanzi.length).toBeGreaterThan(0)
      const foundHanzi = result.data?.hanzi.find((h) => h.simplified === "好")
      expect(foundHanzi?.hskLevels).toContain("new-1")
    })

    it("should support multi-character hanzi", async () => {
      const result = await searchHanzi("中国", undefined, 20, 0)

      expect(result.success).toBe(true)
      expect(result.data?.hanzi.length).toBeGreaterThan(0)
      const foundHanzi = result.data?.hanzi.find((h) => h.simplified === "中国")
      expect(foundHanzi).toBeDefined()
      expect(foundHanzi?.traditional).toBe("中國")
      expect(foundHanzi?.pinyin).toBe("zhōng guó")
      expect(foundHanzi?.meaning).toBe("China")
    })

    it("should return empty for non-existent hanzi", async () => {
      const result = await searchHanzi("不存在的字", undefined, 20, 0)

      expect(result.success).toBe(true)
      expect(result.data?.hanzi.length).toBe(0)
      expect(result.data?.total).toBe(0)
    })

    it("should support pagination", async () => {
      // Create multiple hanzi to test pagination
      for (let i = 0; i < 25; i++) {
        const h = await prisma.hanzi.create({
          data: { simplified: `测${i}`, radical: null, frequency: i },
        })
        const form = await prisma.hanziForm.create({
          data: {
            hanziId: h.id,
            traditional: `測${i}`,
            isDefault: true,
          },
        })
        await prisma.hanziTranscription.create({
          data: { formId: form.id, type: "pinyin", value: `cè ${i}` },
        })
        await prisma.hanziMeaning.create({
          data: {
            formId: form.id,
            languageId: englishLanguage.id,
            meaning: `test ${i}`,
            orderIndex: 0,
          },
        })
      }

      const page1 = await searchHanzi("测", undefined, 10, 0)
      const page2 = await searchHanzi("测", undefined, 10, 10)

      expect(page1.success).toBe(true)
      expect(page1.data?.hanzi.length).toBe(10)
      expect(page1.data?.hasMore).toBe(true)

      expect(page2.success).toBe(true)
      expect(page2.data?.hanzi.length).toBeGreaterThan(0)

      // Check that results are different
      const page1Ids = page1.data?.hanzi.map((h) => h.id) || []
      const page2Ids = page2.data?.hanzi.map((h) => h.id) || []
      expect(page1Ids).not.toEqual(page2Ids)
    })

    it("should validate required query parameter", async () => {
      const result = await searchHanzi("", undefined, 20, 0)

      expect(result.success).toBe(false)
      expect(result.message).toBe("Validation failed")
      expect(result.errors).toBeDefined()
    })
  })

  describe("getHanzi", () => {
    it("should get complete hanzi details", async () => {
      const result = await getHanzi(hanzi1.id)

      expect(result.success).toBe(true)
      expect(result.data).toBeDefined()
      expect(result.data?.simplified).toBe("好")
      expect(result.data?.radical).toBe("女")
      expect(result.data?.frequency).toBe(100)

      // Check forms
      expect(result.data?.forms.length).toBeGreaterThan(0)
      const defaultForm = result.data?.forms.find((f) => f.isDefault)
      expect(defaultForm).toBeDefined()
      expect(defaultForm?.traditional).toBe("好")

      // Check transcriptions
      expect(defaultForm?.transcriptions.length).toBe(2)
      const pinyinTrans = defaultForm?.transcriptions.find((t) => t.type === "pinyin")
      expect(pinyinTrans?.value).toBe("hǎo")

      // Check meanings
      expect(defaultForm?.meanings.length).toBeGreaterThan(0)
      expect(defaultForm?.meanings[0].meaning).toBe("good, well")
      expect(defaultForm?.meanings[0].language).toBe("en")

      // Check classifiers
      expect(defaultForm?.classifiers.length).toBe(1)
      expect(defaultForm?.classifiers[0].classifier).toBe("个")

      // Check HSK levels
      expect(result.data?.hskLevels.length).toBe(1)
      expect(result.data?.hskLevels[0].level).toBe("new-1")

      // Check parts of speech
      expect(result.data?.partsOfSpeech.length).toBe(1)
      expect(result.data?.partsOfSpeech[0].pos).toBe("adj")
    })

    it("should handle multi-character hanzi", async () => {
      const result = await getHanzi(hanzi3.id)

      expect(result.success).toBe(true)
      expect(result.data?.simplified).toBe("中国")
      expect(result.data?.forms[0].traditional).toBe("中國")
      expect(result.data?.forms[0].transcriptions[0].value).toBe("zhōng guó")
      expect(result.data?.forms[0].meanings[0].meaning).toBe("China")
    })

    it("should return error for non-existent hanzi", async () => {
      const result = await getHanzi("non-existent-id")

      expect(result.success).toBe(false)
      expect(result.message).toBe("Hanzi not found")
    })

    it("should validate required id parameter", async () => {
      const result = await getHanzi("")

      expect(result.success).toBe(false)
      expect(result.message).toBe("Validation failed")
    })
  })

  describe("getHanziBySimplified", () => {
    it("should get hanzi by simplified character", async () => {
      const result = await getHanziBySimplified("好")

      expect(result.success).toBe(true)
      expect(result.data).toBeDefined()
      expect(result.data?.simplified).toBe("好")
      expect(result.data?.traditional).toBe("好")
      expect(result.data?.pinyin).toBe("hǎo")
      expect(result.data?.meaning).toBe("good, well")
      expect(result.data?.hskLevels).toContain("new-1")
    })

    it("should work with multi-character words", async () => {
      const result = await getHanziBySimplified("中国")

      expect(result.success).toBe(true)
      expect(result.data?.simplified).toBe("中国")
      expect(result.data?.traditional).toBe("中國")
      expect(result.data?.pinyin).toBe("zhōng guó")
      expect(result.data?.meaning).toBe("China")
    })

    it("should return error for non-existent character", async () => {
      const result = await getHanziBySimplified("不存在")

      expect(result.success).toBe(false)
      expect(result.message).toBe("Hanzi not found")
    })

    it("should validate required char parameter", async () => {
      const result = await getHanziBySimplified("")

      expect(result.success).toBe(false)
      expect(result.message).toBe("Validation failed")
    })
  })
})
