import { beforeEach, describe, expect, it } from "vitest"
import { flushPromises, mount } from "@vue/test-utils"
import { defineComponent, h, Suspense } from "vue"
import { createPinia, setActivePinia } from "pinia"
import ShowPage from "@/pages/ShowPage.vue"
import { __clearElementCache, preloadElement } from "@/engine/useElementLoader"
import { __clearCardCache, preloadCard } from "@/engine/useCardLoader"
import { __resetIdCounter } from "@/adapters"

/**
 * End-to-end smoke: feed ShowPage a config in the legacy v1 shape and
 * assert that it renders correctly, exercising:
 *   - v1 detection at the boundary (no schemaVersion: "v1" hint)
 *   - card type translation (fields_list → element-list)
 *   - field type translation (text → input/text, select → option-select/select)
 *   - column key translation (colsMd → columnsMd)
 *   - condition param translation (field/operator → name/logic)
 */
function mountInSuspense(component: unknown, props: Record<string, unknown>) {
  const Host = defineComponent({
    setup() {
      return () =>
        h(Suspense, null, {
          // eslint-disable-next-line @typescript-eslint/no-explicit-any
          default: () => h(component as any, props),
        })
    },
  })
  return mount(Host)
}

describe("ShowPage with v1 JSON config", () => {
  beforeEach(async () => {
    setActivePinia(createPinia())
    __clearElementCache()
    __clearCardCache()
    __resetIdCounter()
    await preloadCard("element-list")
    await preloadElement("input.text")
    await preloadElement("option-select.select")
  })

  it("renders a fields_list with v1 field types into the engine", async () => {
    const v1Config = {
      title: "Profile",
      tabsList: [
        {
          title: "Details",
          tabId: "details",
          cards: [
            {
              type: "fields_list",
              title: "Personal information",
              fieldsList: [
                {
                  type: "text",
                  name: "first_name",
                  label: "First name",
                  required: true,
                  cols: 12,
                  colsMd: 6,
                },
                {
                  type: "text",
                  name: "last_name",
                  label: "Last name",
                  colsMd: 6,
                },
              ],
            },
          ],
        },
      ],
    }

    const wrapper = mountInSuspense(ShowPage, {
      config: v1Config,
      item: { first_name: "Stephen", last_name: "Peek" },
    })
    await flushPromises()
    await flushPromises()

    expect(wrapper.text()).toContain("Profile")
    expect(wrapper.text()).toContain("First name")
    expect(wrapper.text()).toContain("Last name")
    expect(wrapper.text()).toContain("Personal information")
    expect(wrapper.findAll("input").length).toBeGreaterThanOrEqual(2)
  })

  it("translates v1 conditionParams (field/operator) to v2 logic", async () => {
    const v1Config = {
      title: "Conditional",
      tabsList: [
        {
          title: "Tab",
          tabId: "t",
          cards: [
            {
              type: "fields_list",
              fieldsList: [
                {
                  type: "text",
                  name: "always_visible",
                  label: "Always",
                },
                {
                  type: "text",
                  name: "admin_only",
                  label: "Admin only",
                  conditionParams: [
                    { field: "role", operator: "equals", value: "admin" },
                  ],
                },
              ],
            },
          ],
        },
      ],
    }

    const userWrapper = mountInSuspense(ShowPage, {
      config: v1Config,
      item: { role: "user" },
    })
    await flushPromises()
    await flushPromises()
    expect(userWrapper.text()).toContain("Always")
    expect(userWrapper.text()).not.toContain("Admin only")

    const adminWrapper = mountInSuspense(ShowPage, {
      config: v1Config,
      item: { role: "admin" },
    })
    await flushPromises()
    await flushPromises()
    expect(adminWrapper.text()).toContain("Always")
    expect(adminWrapper.text()).toContain("Admin only")
  })

  it("accepts a v2 config unchanged (no adapter applied)", async () => {
    const v2Config = {
      title: "Profile",
      tabsList: [
        {
          title: "Details",
          tabId: "details",
          cards: [
            {
              id: "card-1",
              cardType: "element-list",
              title: "Personal information",
              elementList: ["el-1"],
            },
          ],
        },
      ],
      cards: {
        "card-1": {
          id: "card-1",
          cardType: "element-list",
          title: "Personal information",
          elementList: ["el-1"],
        },
      },
      elements: {
        "el-1": {
          id: "el-1",
          type: "input.text",
          name: "first_name",
          label: "First name",
        },
      },
    }
    const wrapper = mountInSuspense(ShowPage, { config: v2Config, item: {} })
    await flushPromises()
    await flushPromises()
    expect(wrapper.text()).toContain("First name")
  })
})
