import { beforeEach, describe, expect, it } from "vitest"
import { defineComponent, h, Suspense } from "vue"
import { flushPromises, mount } from "@vue/test-utils"
import { createPinia, setActivePinia } from "pinia"
import type { CardElement } from "@/definitions/elements"
import type { InputElement } from "@/definitions/elements/InputElement"
import ElementListCard from "./ElementListCard.vue"
import {
  __clearElementCache,
  preloadElement,
} from "@/engine/useElementLoader"

function makeInput(
  id: string,
  overrides: Partial<InputElement> = {},
): InputElement {
  return {
    id,
    type: "input.text",
    name: id,
    label: `Label for ${id}`,
    ...overrides,
  } as InputElement
}

function mountWithSuspense(props: Record<string, unknown>) {
  const Host = defineComponent({
    setup() {
      return () =>
        h(Suspense, null, {
          default: () =>
            // eslint-disable-next-line @typescript-eslint/no-explicit-any
            h(ElementListCard as any, props),
        })
    },
  })
  return mount(Host)
}

describe("ElementListCard", () => {
  beforeEach(async () => {
    setActivePinia(createPinia())
    __clearElementCache()
    await preloadElement("input.text")
  })

  it("mounts without error", () => {
    const wrapper = mount(ElementListCard, { props: {} })
    expect(wrapper.exists()).toBe(true)
  })

  it("renders an empty elements array cleanly", () => {
    const wrapper = mount(ElementListCard, {
      props: { elements: [] },
    })
    expect(wrapper.exists()).toBe(true)
    expect(wrapper.findAll("[data-element-id]").length).toBe(0)
  })

  it("renders the title when set", () => {
    const wrapper = mount(ElementListCard, {
      props: { title: "Primary information" },
    })
    expect(wrapper.text()).toContain("Primary information")
  })

  it("renders the subtitle when set", () => {
    const wrapper = mount(ElementListCard, {
      props: { title: "Header", subtitle: "Helper text" },
    })
    expect(wrapper.text()).toContain("Helper text")
  })

  it("renders the card chrome by default (showCard !== false)", () => {
    const wrapper = mount(ElementListCard, { props: {} })
    expect(wrapper.find("[data-testid='element-list-bare']").exists()).toBe(
      false,
    )
  })

  it("renders without chrome when showCard is false", () => {
    const wrapper = mount(ElementListCard, {
      props: { showCard: false },
    })
    expect(wrapper.find("[data-testid='element-list-bare']").exists()).toBe(
      true,
    )
  })

  it("renders each provided element", async () => {
    const element: CardElement = makeInput("first-name", {
      label: "First name",
    })
    const wrapper = mountWithSuspense({
      elements: [element],
    })
    await flushPromises()
    expect(wrapper.text()).toContain("First name")
    expect(wrapper.find("input").exists()).toBe(true)
  })

  it("renders multiple elements in order", async () => {
    const first: CardElement = makeInput("first", { label: "First field" })
    const second: CardElement = makeInput("second", { label: "Second field" })
    const wrapper = mountWithSuspense({
      elements: [first, second],
    })
    await flushPromises()
    expect(wrapper.findAll("[data-element-id]").length).toBe(2)
  })
})
