import { beforeEach, describe, expect, it } from "vitest"
import { flushPromises, mount } from "@vue/test-utils"
import { createPinia, setActivePinia } from "pinia"
import CodeEditor from "./CodeEditor.vue"

async function mountEditor(
  props: Partial<InstanceType<typeof CodeEditor>["$props"]> = {},
) {
  const wrapper = mount(CodeEditor, { props, attachTo: document.body })
  await flushPromises()
  return wrapper
}

describe("CodeEditor (props-based composition)", () => {
  beforeEach(() => {
    setActivePinia(createPinia())
  })

  it("mounts and renders the editor and toolbar", async () => {
    const wrapper = await mountEditor({ label: "Field label" })
    expect(wrapper.find("[data-testid='code-editor']").exists()).toBe(true)
    expect(wrapper.find("[data-testid='code-editor-content']").exists()).toBe(true)
    expect(wrapper.text()).toContain("Field label")
  })

  it("shows the active language in the toolbar", async () => {
    const wrapper = await mountEditor({ language: "typescript" })
    expect(wrapper.text()).toContain("TypeScript")
  })

  it("defaults to JavaScript language", async () => {
    const wrapper = await mountEditor()
    expect(wrapper.text()).toContain("JavaScript")
  })

  it("renders the label via FieldFrame", async () => {
    const wrapper = await mountEditor({ label: "Source code" })
    expect(wrapper.text()).toContain("Source code")
  })

  it("hides the label when hideLabel is true", async () => {
    const wrapper = await mountEditor({ label: "Should hide", hideLabel: true })
    expect(wrapper.find("[data-testid='field-frame-label']").exists()).toBe(false)
  })

  it("renders errors from props", async () => {
    const wrapper = await mountEditor({ errors: ["Invalid syntax"] })
    expect(wrapper.text()).toContain("Invalid syntax")
    expect(wrapper.find("[data-testid='field-frame-errors']").exists()).toBe(true)
  })

  it("applies destructive border when errors are present", async () => {
    const wrapper = await mountEditor({ errors: ["Bad"] })
    expect(wrapper.html()).toContain("border-destructive")
  })

  it("renders help text", async () => {
    const wrapper = await mountEditor({ helpText: "Write JavaScript here" })
    expect(wrapper.text()).toContain("Write JavaScript here")
  })

  it("shows the Format button only for JSON language", async () => {
    const jsonWrapper = await mountEditor({ language: "json" })
    expect(jsonWrapper.find("[data-testid='code-editor-format']").exists()).toBe(true)

    const jsWrapper = await mountEditor({ language: "javascript" })
    expect(jsWrapper.find("[data-testid='code-editor-format']").exists()).toBe(false)
  })

  it("disables the toolbar when readonly is set", async () => {
    const wrapper = await mountEditor({ readonly: true })
    expect(wrapper.html()).toContain("pointer-events-none")
  })

  it("disables the toolbar when disabled is set", async () => {
    const wrapper = await mountEditor({ disabled: true })
    expect(wrapper.html()).toContain("pointer-events-none")
  })

  it("renders the language selector trigger", async () => {
    const wrapper = await mountEditor({ language: "python" })
    expect(wrapper.find("[data-testid='code-editor-lang-trigger']").exists()).toBe(true)
    expect(wrapper.find("[data-testid='code-editor-lang-trigger']").text()).toContain("Python")
  })

  it("works without any props at all", async () => {
    const wrapper = await mountEditor()
    expect(wrapper.find("[data-testid='code-editor']").exists()).toBe(true)
  })
})
