import { describe, it, expect } from "vitest"
import { mount } from "@vue/test-utils"
import {
  Table,
  TableBody,
  TableCaption,
  TableCell,
  TableFooter,
  TableHead,
  TableHeader,
  TableRow,
} from "."

describe("Table", () => {
  describe("Table root", () => {
    it("renders a table inside a wrapper div", () => {
      const wrapper = mount(Table, { slots: { default: "<tbody><tr><td>x</td></tr></tbody>" } })
      expect(wrapper.element.tagName).toBe("DIV")
      expect(wrapper.find("table").exists()).toBe(true)
    })

    it("has overflow wrapper classes", () => {
      const wrapper = mount(Table)
      expect(wrapper.classes()).toContain("relative")
      expect(wrapper.classes()).toContain("w-full")
      expect(wrapper.classes()).toContain("overflow-auto")
    })

    it("table has base classes", () => {
      const wrapper = mount(Table)
      const table = wrapper.find("table")
      expect(table.classes()).toContain("w-full")
      expect(table.classes()).toContain("caption-bottom")
      expect(table.classes()).toContain("text-sm")
    })

    it("accepts custom class on table", () => {
      const wrapper = mount(Table, { props: { class: "custom-table" } })
      const table = wrapper.find("table")
      expect(table.classes()).toContain("custom-table")
      expect(table.classes()).toContain("w-full")
    })
  })

  describe("TableHeader", () => {
    it("renders as a thead element", () => {
      const wrapper = mount(TableHeader, { slots: { default: "<tr><th>a</th></tr>" } })
      expect(wrapper.element.tagName).toBe("THEAD")
    })

    it("has border child selector class", () => {
      const wrapper = mount(TableHeader)
      expect(wrapper.classes()).toContain("[&_tr]:border-b")
    })

    it("accepts custom class", () => {
      const wrapper = mount(TableHeader, { props: { class: "custom-thead" } })
      expect(wrapper.classes()).toContain("custom-thead")
    })
  })

  describe("TableBody", () => {
    it("renders as a tbody element", () => {
      const wrapper = mount(TableBody, { slots: { default: "<tr><td>x</td></tr>" } })
      expect(wrapper.element.tagName).toBe("TBODY")
    })

    it("has last-child border selector", () => {
      const wrapper = mount(TableBody)
      expect(wrapper.classes()).toContain("[&_tr:last-child]:border-0")
    })

    it("accepts custom class", () => {
      const wrapper = mount(TableBody, { props: { class: "custom-tbody" } })
      expect(wrapper.classes()).toContain("custom-tbody")
    })
  })

  describe("TableFooter", () => {
    it("renders as a tfoot element", () => {
      const wrapper = mount(TableFooter, { slots: { default: "<tr><td>x</td></tr>" } })
      expect(wrapper.element.tagName).toBe("TFOOT")
    })

    it("has base classes", () => {
      const wrapper = mount(TableFooter)
      expect(wrapper.classes()).toContain("border-t")
      expect(wrapper.classes()).toContain("bg-muted/50")
      expect(wrapper.classes()).toContain("font-medium")
    })
  })

  describe("TableRow", () => {
    it("renders as a tr element", () => {
      const wrapper = mount(TableRow, { slots: { default: "<td>x</td>" } })
      expect(wrapper.element.tagName).toBe("TR")
    })

    it("has base classes", () => {
      const wrapper = mount(TableRow)
      const classes = wrapper.classes()
      for (const cls of [
        "border-b",
        "transition-colors",
        "hover:bg-muted/50",
        "data-[state=selected]:bg-muted",
      ]) {
        expect(classes).toContain(cls)
      }
    })

    it("accepts custom class", () => {
      const wrapper = mount(TableRow, { props: { class: "custom-row" } })
      expect(wrapper.classes()).toContain("custom-row")
    })
  })

  describe("TableHead", () => {
    it("renders as a th element", () => {
      const wrapper = mount(TableHead, { slots: { default: "Header" } })
      expect(wrapper.element.tagName).toBe("TH")
      expect(wrapper.text()).toBe("Header")
    })

    it("has base classes", () => {
      const wrapper = mount(TableHead)
      const classes = wrapper.classes()
      for (const cls of [
        "h-12",
        "px-4",
        "text-left",
        "align-middle",
        "font-medium",
        "text-muted-foreground",
      ]) {
        expect(classes).toContain(cls)
      }
    })

    it("accepts custom class", () => {
      const wrapper = mount(TableHead, { props: { class: "custom-head" } })
      expect(wrapper.classes()).toContain("custom-head")
    })
  })

  describe("TableCell", () => {
    it("renders as a td element", () => {
      const wrapper = mount(TableCell, { slots: { default: "Cell" } })
      expect(wrapper.element.tagName).toBe("TD")
      expect(wrapper.text()).toBe("Cell")
    })

    it("has base classes", () => {
      const wrapper = mount(TableCell)
      expect(wrapper.classes()).toContain("p-4")
      expect(wrapper.classes()).toContain("align-middle")
    })

    it("accepts custom class", () => {
      const wrapper = mount(TableCell, { props: { class: "custom-cell" } })
      expect(wrapper.classes()).toContain("custom-cell")
    })
  })

  describe("TableCaption", () => {
    it("renders as a caption element", () => {
      const wrapper = mount(TableCaption, { slots: { default: "Caption" } })
      expect(wrapper.element.tagName).toBe("CAPTION")
      expect(wrapper.text()).toBe("Caption")
    })

    it("has base classes", () => {
      const wrapper = mount(TableCaption)
      expect(wrapper.classes()).toContain("mt-4")
      expect(wrapper.classes()).toContain("text-sm")
      expect(wrapper.classes()).toContain("text-muted-foreground")
    })

    it("accepts custom class", () => {
      const wrapper = mount(TableCaption, { props: { class: "custom-caption" } })
      expect(wrapper.classes()).toContain("custom-caption")
    })
  })

  describe("composition", () => {
    it("renders a full table with header, body, footer and caption", () => {
      const wrapper = mount({
        components: {
          Table,
          TableHeader,
          TableBody,
          TableFooter,
          TableRow,
          TableHead,
          TableCell,
          TableCaption,
        },
        template: `
          <Table>
            <TableCaption>Recent</TableCaption>
            <TableHeader>
              <TableRow>
                <TableHead>Name</TableHead>
                <TableHead>Status</TableHead>
              </TableRow>
            </TableHeader>
            <TableBody>
              <TableRow>
                <TableCell>Alice</TableCell>
                <TableCell>Active</TableCell>
              </TableRow>
            </TableBody>
            <TableFooter>
              <TableRow>
                <TableCell>Total</TableCell>
                <TableCell>1</TableCell>
              </TableRow>
            </TableFooter>
          </Table>
        `,
      })

      expect(wrapper.find("table").exists()).toBe(true)
      expect(wrapper.find("caption").text()).toBe("Recent")
      expect(wrapper.find("thead").exists()).toBe(true)
      expect(wrapper.find("tbody").exists()).toBe(true)
      expect(wrapper.find("tfoot").exists()).toBe(true)
      expect(wrapper.findAll("th")).toHaveLength(2)
      expect(wrapper.findAll("tr").length).toBeGreaterThanOrEqual(3)
      expect(wrapper.text()).toContain("Alice")
    })
  })
})
