import { mount } from "@vue/test-utils"
import { afterEach, describe, expect, it, vi } from "vitest"
import EditorSuggestionMenu from "@/components/EditorSuggestionMenu.vue"

interface MenuVM {
  forwardKey(key: string): void
}

function createWrapper(props: Record<string, unknown> = {}) {
  return mount(EditorSuggestionMenu, {
    props: {
      groups: [],
      position: { x: 0, y: 0 },
      query: "",
      active: false,
      ...props,
    },
    attachTo: document.body,
  }) as unknown as {
    vm: MenuVM & Record<string, unknown>
    emitted: () => Record<string, unknown[]>
  }
}

describe("EditorSuggestionMenu", () => {
  afterEach(() => {
    document.body.querySelector("[data-command-palette]")?.remove()
  })

  it("renders nothing when active is false", () => {
    createWrapper({ active: false })
    expect(document.body.querySelector("[data-command-palette]")).toBeNull()
  })

  it("renders palette in document body when active is true", () => {
    createWrapper({ active: true })
    const el = document.body.querySelector("[data-command-palette]")
    expect(el).not.toBeNull()
  })

  it("positions the menu correctly", () => {
    createWrapper({ active: true, position: { x: 100, y: 200 } })
    const el = document.body.querySelector(
      "[data-command-palette]",
    ) as HTMLElement
    expect(el.style.top).toBe("224px")
    expect(el.style.left).toBe("100px")
  })

  it("exposes forwardKey via template ref", () => {
    const wrapper = createWrapper({ active: true })
    expect(typeof wrapper.vm.forwardKey).toBe("function")
  })

  it("renders items from groups", () => {
    const groups = [
      {
        id: "test",
        label: "Test",
        items: [
          { label: "Item 1", icon: "i-lucide-text", onSelect: () => {} },
          { label: "Item 2", onSelect: () => {} },
        ],
      },
    ]
    createWrapper({ active: true, groups })
    const items = document.body.querySelectorAll(
      "[data-command-palette] [data-highlighted]",
    )
    expect(items.length).toBe(1)
    expect(items[0]?.textContent).toContain("Item 1")
  })

  it("highlights first item by default", () => {
    const groups = [
      {
        id: "test",
        items: [
          { label: "First", onSelect: () => {} },
          { label: "Second", onSelect: () => {} },
        ],
      },
    ]
    createWrapper({ active: true, groups })
    const highlighted = document.body.querySelectorAll("[data-highlighted]")
    expect(highlighted.length).toBe(1)
    expect(highlighted[0]?.textContent).toContain("First")
  })

  it("forwardKey ArrowDown moves highlight to next item", async () => {
    const groups = [
      {
        id: "test",
        items: [
          { label: "First", onSelect: () => {} },
          { label: "Second", onSelect: () => {} },
        ],
      },
    ]
    const wrapper = createWrapper({ active: true, groups })
    wrapper.vm.forwardKey("ArrowDown")
    await wrapper.vm.$nextTick()
    const highlighted = document.body.querySelectorAll("[data-highlighted]")
    expect(highlighted.length).toBe(1)
    expect(highlighted[0]?.textContent).toContain("Second")
  })

  it("forwardKey ArrowUp wraps to last item", async () => {
    const groups = [
      {
        id: "test",
        items: [
          { label: "First", onSelect: () => {} },
          { label: "Second", onSelect: () => {} },
        ],
      },
    ]
    const wrapper = createWrapper({ active: true, groups })
    wrapper.vm.forwardKey("ArrowUp")
    await wrapper.vm.$nextTick()
    const highlighted = document.body.querySelectorAll("[data-highlighted]")
    expect(highlighted.length).toBe(1)
    expect(highlighted[0]?.textContent).toContain("Second")
  })

  it("forwardKey Enter selects item and emits close", async () => {
    const onSelect = vi.fn()
    const groups = [
      {
        id: "test",
        items: [{ label: "Item", onSelect }],
      },
    ]
    const wrapper = createWrapper({ active: true, groups })
    wrapper.vm.forwardKey("Enter")
    await wrapper.vm.$nextTick()
    expect(onSelect).toHaveBeenCalled()
    expect(wrapper.emitted().close).toBeTruthy()
  })

  it("forwardKey Escape emits close", () => {
    const wrapper = createWrapper({ active: true })
    wrapper.vm.forwardKey("Escape")
    expect(wrapper.emitted().close).toBeTruthy()
  })

  it("renders group label", () => {
    const groups = [
      {
        id: "test",
        label: "Group Label",
        items: [{ label: "Item", onSelect: () => {} }],
      },
    ]
    createWrapper({ active: true, groups })
    expect(document.body.textContent).toContain("Group Label")
  })

  it("renders kbd hints", () => {
    const groups = [
      {
        id: "test",
        items: [{ label: "Item", kbds: ["⌘B"], onSelect: () => {} }],
      },
    ]
    createWrapper({ active: true, groups })
    expect(document.body.textContent).toContain("⌘B")
  })

  it("renders suffix", () => {
    const groups = [
      {
        id: "test",
        items: [{ label: "Item", suffix: "Page", onSelect: () => {} }],
      },
    ]
    createWrapper({ active: true, groups })
    expect(document.body.textContent).toContain("Page")
  })
})
