import { describe, it, expect } from "vitest"
import { mount } from "@vue/test-utils"
import { Textarea } from "."

describe("Textarea", () => {
  describe("default rendering", () => {
    it("renders as a textarea element", () => {
      const wrapper = mount(Textarea)
      expect(wrapper.element.tagName).toBe("TEXTAREA")
    })

    it("has base layout classes", () => {
      const wrapper = mount(Textarea)
      const classes = wrapper.classes()
      for (const cls of [
        "flex",
        "min-h-20",
        "w-full",
        "rounded-md",
        "border",
        "border-input",
        "bg-background",
        "px-3",
        "py-2",
        "text-sm",
      ]) {
        expect(classes).toContain(cls)
      }
    })

    it("has focus-visible classes", () => {
      const wrapper = mount(Textarea)
      const classes = wrapper.classes()
      for (const cls of [
        "focus-visible:outline-none",
        "focus-visible:ring-2",
        "focus-visible:ring-ring",
        "focus-visible:ring-offset-2",
      ]) {
        expect(classes).toContain(cls)
      }
    })

    it("has disabled classes", () => {
      const wrapper = mount(Textarea)
      expect(wrapper.classes()).toContain("disabled:cursor-not-allowed")
      expect(wrapper.classes()).toContain("disabled:opacity-50")
    })

    it("has placeholder classes", () => {
      const wrapper = mount(Textarea)
      expect(wrapper.classes()).toContain("placeholder:text-muted-foreground")
    })

    it("defaults rows to 3", () => {
      const wrapper = mount(Textarea)
      expect(wrapper.attributes("rows")).toBe("3")
    })
  })

  describe("v-model / modelValue", () => {
    it("accepts string modelValue", () => {
      const wrapper = mount(Textarea, { props: { modelValue: "hello" } })
      expect((wrapper.element as HTMLTextAreaElement).value).toBe("hello")
    })

    it("uses defaultValue when no modelValue is provided", () => {
      const wrapper = mount(Textarea, { props: { defaultValue: "draft" } })
      expect((wrapper.element as HTMLTextAreaElement).value).toBe("draft")
    })

    it("emits update:modelValue when typing", async () => {
      const wrapper = mount(Textarea, { props: { modelValue: "" } })
      await wrapper.setValue("multi\nline")
      expect(wrapper.emitted("update:modelValue")).toBeTruthy()
      expect(wrapper.emitted("update:modelValue")![0]).toEqual(["multi\nline"])
    })

    it("updates element value when modelValue prop changes", async () => {
      const wrapper = mount(Textarea, { props: { modelValue: "v1" } })
      expect((wrapper.element as HTMLTextAreaElement).value).toBe("v1")
      await wrapper.setProps({ modelValue: "v2" })
      expect((wrapper.element as HTMLTextAreaElement).value).toBe("v2")
    })
  })

  describe("rows / cols", () => {
    it.each([1, 3, 6, 10, 20] as const)("respects rows=%s", (rows) => {
      const wrapper = mount(Textarea, { props: { rows } })
      expect(wrapper.attributes("rows")).toBe(String(rows))
    })

    it("respects cols prop", () => {
      const wrapper = mount(Textarea, { props: { cols: 40 } })
      expect(wrapper.attributes("cols")).toBe("40")
    })
  })

  describe("custom class", () => {
    it("merges custom class with base classes", () => {
      const wrapper = mount(Textarea, { props: { class: "my-custom" } })
      expect(wrapper.classes()).toContain("my-custom")
      expect(wrapper.classes()).toContain("flex")
    })

    it("allows overriding base classes via tailwind-merge", () => {
      const wrapper = mount(Textarea, { props: { class: "min-h-40 bg-blue-500" } })
      expect(wrapper.classes()).toContain("min-h-40")
      expect(wrapper.classes()).toContain("bg-blue-500")
      expect(wrapper.classes()).not.toContain("min-h-20")
      expect(wrapper.classes()).not.toContain("bg-background")
    })
  })

  describe("HTML attribute forwarding", () => {
    it("forwards disabled", () => {
      const wrapper = mount(Textarea, { attrs: { disabled: true } })
      expect(wrapper.attributes("disabled")).toBe("")
    })

    it("forwards readonly", () => {
      const wrapper = mount(Textarea, { attrs: { readonly: true } })
      expect(wrapper.attributes("readonly")).toBe("")
    })

    it("forwards placeholder", () => {
      const wrapper = mount(Textarea, { attrs: { placeholder: "Type here" } })
      expect(wrapper.attributes("placeholder")).toBe("Type here")
    })

    it("forwards id and name", () => {
      const wrapper = mount(Textarea, { attrs: { id: "bio", name: "biography" } })
      expect(wrapper.attributes("id")).toBe("bio")
      expect(wrapper.attributes("name")).toBe("biography")
    })

    it("forwards aria-label", () => {
      const wrapper = mount(Textarea, { attrs: { "aria-label": "Bio" } })
      expect(wrapper.attributes("aria-label")).toBe("Bio")
    })
  })
})
