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

describe("Label", () => {
  describe("default rendering", () => {
    it("renders as a label element", () => {
      const wrapper = mount(Label, { slots: { default: "Name" } })
      expect(wrapper.element.tagName).toBe("LABEL")
    })

    it("renders slot content", () => {
      const wrapper = mount(Label, { slots: { default: "First name" } })
      expect(wrapper.text()).toBe("First name")
    })

    it("has base typography classes", () => {
      const wrapper = mount(Label, { slots: { default: "X" } })
      const classes = wrapper.classes()
      for (const cls of ["text-sm", "font-medium", "leading-none"]) {
        expect(classes).toContain(cls)
      }
    })

    it("has peer-disabled classes", () => {
      const wrapper = mount(Label, { slots: { default: "X" } })
      expect(wrapper.classes()).toContain("peer-disabled:cursor-not-allowed")
      expect(wrapper.classes()).toContain("peer-disabled:opacity-70")
    })
  })

  describe("for attribute forwarding", () => {
    it("forwards `for` to the rendered <label>", () => {
      const wrapper = mount(Label, {
        props: { for: "email" },
        slots: { default: "Email" },
      })
      expect(wrapper.attributes("for")).toBe("email")
    })
  })

  describe("required variant", () => {
    it("does not add asterisk by default", () => {
      const wrapper = mount(Label, { slots: { default: "Name" } })
      expect(wrapper.classes()).not.toContain("after:content-['*']")
    })

    it("adds asterisk classes when required=true", () => {
      const wrapper = mount(Label, {
        props: { required: true },
        slots: { default: "Name" },
      })
      const classes = wrapper.classes()
      expect(classes).toContain("after:ml-0.5")
      expect(classes).toContain("after:text-destructive")
      expect(classes).toContain("after:content-['*']")
    })

    it("does not add asterisk when required=false explicitly", () => {
      const wrapper = mount(Label, {
        props: { required: false },
        slots: { default: "Name" },
      })
      expect(wrapper.classes()).not.toContain("after:content-['*']")
    })
  })

  describe("custom class", () => {
    it("merges custom class with base classes", () => {
      const wrapper = mount(Label, {
        props: { class: "uppercase tracking-wide" },
        slots: { default: "Name" },
      })
      expect(wrapper.classes()).toContain("uppercase")
      expect(wrapper.classes()).toContain("tracking-wide")
      expect(wrapper.classes()).toContain("text-sm")
    })

    it("merges custom class with required variant", () => {
      const wrapper = mount(Label, {
        props: { required: true, class: "uppercase" },
        slots: { default: "Name" },
      })
      expect(wrapper.classes()).toContain("uppercase")
      expect(wrapper.classes()).toContain("after:content-['*']")
    })

    it("allows overriding base text size via tailwind-merge", () => {
      const wrapper = mount(Label, {
        props: { class: "text-lg" },
        slots: { default: "Name" },
      })
      expect(wrapper.classes()).toContain("text-lg")
      expect(wrapper.classes()).not.toContain("text-sm")
    })
  })

  describe("slot content", () => {
    it("renders HTML slot", () => {
      const wrapper = mount(Label, {
        slots: { default: '<span class="inner">Name</span>' },
      })
      expect(wrapper.find(".inner").exists()).toBe(true)
    })

    it("renders component slot", () => {
      const Inner = { template: '<span class="vinner">X</span>' }
      const wrapper = mount(Label, { slots: { default: h(Inner) } })
      expect(wrapper.find(".vinner").exists()).toBe(true)
    })
  })
})
