import { beforeEach, describe, expect, it } from "vitest"
import { mount } from "@vue/test-utils"
import { createPinia, setActivePinia } from "pinia"
import PresetBuilder from "./PresetBuilder.vue"
import {
  __resetPresetBuilderIdCounter,
  usePresetBuilderStore,
  type PresetBuilderSchema,
} from "@/stores/presetBuilderStore"
import {
  __resetFormBuilderIdCounter,
  useFormBuilderStore,
} from "@/stores/formBuilderStore"

const BUILDER_ID = "preset-test"

describe("PresetBuilder", () => {
  beforeEach(() => {
    setActivePinia(createPinia())
    __resetPresetBuilderIdCounter()
    __resetFormBuilderIdCounter()
  })

  it("renders the preset envelope with name + description inputs", () => {
    const wrapper = mount(PresetBuilder, { props: { builderId: BUILDER_ID } })
    expect(wrapper.find("[data-testid='preset-builder']").exists()).toBe(true)
    expect(
      wrapper.find("[data-testid='preset-builder-name']").exists(),
    ).toBe(true)
    expect(
      wrapper.find("[data-testid='preset-builder-description']").exists(),
    ).toBe(true)
  })

  it("renders the embedded FormBuilder", () => {
    const wrapper = mount(PresetBuilder, { props: { builderId: BUILDER_ID } })
    expect(wrapper.find("[data-testid='form-builder']").exists()).toBe(true)
    expect(
      wrapper.find("[data-testid='form-builder-palette']").exists(),
    ).toBe(true)
  })

  it("writes name + description into the store on input", async () => {
    const wrapper = mount(PresetBuilder, { props: { builderId: BUILDER_ID } })
    await wrapper
      .find("[data-testid='preset-builder-name']")
      .setValue("Brand kit")
    await wrapper
      .find("[data-testid='preset-builder-description']")
      .setValue("Default colors and type")

    const store = usePresetBuilderStore()
    const state = store.getState(BUILDER_ID)
    expect(state.presetName).toBe("Brand kit")
    expect(state.presetDescription).toBe("Default colors and type")
  })

  it("seeds both stores from modelValue on mount", () => {
    const seed: PresetBuilderSchema = {
      presetName: "Initial preset",
      presetDescription: "Pre-loaded",
      schema: {
        rootCardId: "seed-root",
        cards: {
          "seed-root": {
            id: "seed-root",
            cardType: "element-list",
            elementList: ["seed-el"],
          } as never,
        },
        elements: {
          "seed-el": {
            id: "seed-el",
            type: "input.text",
            label: "Seeded label",
          } as never,
        },
      },
    }
    mount(PresetBuilder, {
      props: { builderId: BUILDER_ID, modelValue: seed },
    })

    const presetStore = usePresetBuilderStore()
    expect(presetStore.getState(BUILDER_ID).presetName).toBe(
      "Initial preset",
    )
    expect(presetStore.getState(BUILDER_ID).presetDescription).toBe(
      "Pre-loaded",
    )

    const formStore = useFormBuilderStore()
    const innerId = presetStore.getState(BUILDER_ID).innerBuilderId
    const innerSchema = formStore.getSchema(innerId)
    expect(innerSchema.rootCardId).toBe("seed-root")
    expect(innerSchema.elements["seed-el"]?.label).toBe("Seeded label")
  })

  it("emits update:modelValue with the full preset schema on mutation", async () => {
    const wrapper = mount(PresetBuilder, { props: { builderId: BUILDER_ID } })
    await wrapper
      .find("[data-testid='preset-builder-name']")
      .setValue("Brand kit")
    await wrapper.vm.$nextTick()

    const emitted = wrapper.emitted("update:modelValue")
    expect(emitted).toBeTruthy()
    const last = emitted![emitted!.length - 1] as unknown[]
    const value = last[0] as PresetBuilderSchema
    expect(value.presetName).toBe("Brand kit")
    expect(typeof value.schema).toBe("object")
    expect(typeof value.schema.rootCardId).toBe("string")
  })

  it("adding an element via the inner palette mutates the preset's inner schema", async () => {
    const wrapper = mount(PresetBuilder, { props: { builderId: BUILDER_ID } })
    await wrapper
      .find("[data-testid='form-builder-palette-input']")
      .trigger("click")
    await wrapper
      .find("[data-testid='form-builder-palette-input-text']")
      .trigger("click")

    const presetStore = usePresetBuilderStore()
    const innerId = presetStore.getState(BUILDER_ID).innerBuilderId
    const formStore = useFormBuilderStore()
    const innerSchema = formStore.getSchema(innerId)
    const root = innerSchema.cards[innerSchema.rootCardId] as unknown as {
      elementList: string[]
    }
    expect(root.elementList).toHaveLength(1)
  })
})
