import { mount } from '@vue/test-utils'
import DemoRenderer from '../playground/docs/components/DemoRenderer.vue'
// INFRA-F148: the range / text / cycle 控件 are DS components now — assert on the
// component identity, not on the hand-written class names they used to carry.
import { Slider, InputBoxLine } from '../src/index'
import { progressDescriptor } from '../react-pilot/src/demos/descriptors/progress'
import { buttonDescriptor } from '../react-pilot/src/demos/descriptors/button'
import { topbarDescriptor } from '../react-pilot/src/demos/descriptors/topbar'
import { describe, it, expect } from 'vitest'

describe('DemoRenderer (vue)', () => {
  it('renders all 6 progress sections with correct titles', () => {
    const w = mount(DemoRenderer, { props: { descriptor: progressDescriptor, theme: 'dark', locale: 'en-US' }, global: { provide: { docsTheme: { value: 'dark' } } } })
    const titles = w.findAll('.docs-section__title').map((n) => n.text())
    expect(titles).toEqual(['Figma Coverage', 'Family Matrix', 'Runtime Value', 'Development Usage', 'Status Matrix', 'Interactive: showLabel'])
  })
  it('renders figma-coverage via FigmaMembersGrid (axes chips present)', () => {
    const w = mount(DemoRenderer, { props: { descriptor: progressDescriptor, theme: 'dark', locale: 'en-US' }, global: { provide: { docsTheme: { value: 'dark' } } } })
    expect(w.find('.figma-members-grid').exists()).toBe(true)
  })
  it('renders family-matrix cells + code-block + DS Slider (not a hand-written range)', () => {
    const w = mount(DemoRenderer, { props: { descriptor: progressDescriptor, theme: 'dark', locale: 'en-US' }, global: { provide: { docsTheme: { value: 'dark' } } } })
    expect(w.findAll('.family-matrix__cell').length).toBeGreaterThan(0)
    expect(w.find('.code-block').exists()).toBe(true)
    // INFRA-F148: both halves matter — the first fails if the swap never happened,
    // the second fails if it happened but left the old element behind.
    expect(w.findComponent(Slider).exists()).toBe(true)
    expect(w.find('input.try-range').exists()).toBe(false)
  })

  it('range control drives state through the DS Slider', async () => {
    const w = mount(DemoRenderer, { props: { descriptor: progressDescriptor, theme: 'dark', locale: 'en-US' }, global: { provide: { docsTheme: { value: 'dark' } } } })
    const readout = () => w.find('.try-readout').text()
    expect(readout()).toContain('value = 45%')
    await w.findComponent(Slider).find('input[type="range"]').setValue('80')
    expect(readout()).toContain('value = 80%')
  })
})

describe('DemoRenderer (vue) — Button', () => {
  function mountButton() {
    return mount(DemoRenderer, { props: { descriptor: buttonDescriptor, theme: 'dark', locale: 'en-US' }, global: { provide: { docsTheme: { value: 'dark' } } } })
  }

  it('renders all 9 axis-section titles + 2 info-section titles', () => {
    const w = mountButton()
    const titles = w.findAll('.docs-section__title').map((n) => n.text())
    expect(titles).toEqual([
      'Figma M Coverage', 'Development Usage',
      'Basic Usage', 'Color Buttons', 'Status Buttons', 'Disable Buttons', 'Icon Buttons',
      'Loading Buttons', 'Round Buttons', 'Button Sizes', 'Fixed Width Buttons',
    ])
  })

  it('renders the default "Button" text inside instances', () => {
    const w = mountButton()
    const samples = w.findAll('.review-sample')
    expect(samples.length).toBeGreaterThan(0)
    expect(samples[0].text()).toContain('Button')
  })

  it('renders the code-block card summary paragraph before the <pre>', () => {
    const w = mountButton()
    const codeCard = w.find('.code-block').element.closest('.docs-demo-card')!
    const summary = codeCard.querySelector('.docs-demo-card__summary')
    expect(summary?.textContent).toContain('real Button entry point')
  })

  it('hover flips a default-status sample to status=hover (mouseenter/mouseleave)', async () => {
    const w = mountButton()
    const sample = w.findAll('.review-sample')[0]
    // Baseline: default status, no hover data marker yet.
    expect(sample.find('[data-figma-status="hover"]').exists()).toBe(false)
    await sample.trigger('mouseenter')
    expect(sample.find('[data-figma-status="hover"]').exists()).toBe(true)
    await sample.trigger('mouseleave')
    expect(sample.find('[data-figma-status="hover"]').exists()).toBe(false)
  })

  it('does not bind hover on disable-review samples (status=disable stays disable)', async () => {
    const w = mountButton()
    // Disable Buttons section renders without .review-demo__hint (no hoverPreview on the card).
    const sections = w.findAll('.docs-section')
    const disableSection = sections.find((s) => s.find('.docs-section__title').text() === 'Disable Buttons')!
    expect(disableSection.find('.review-demo__hint').exists()).toBe(false)
    const sample = disableSection.findAll('.review-sample')[0]
    await sample.trigger('mouseenter')
    expect(sample.find('[data-figma-status="disable"]').exists()).toBe(true)
    expect(sample.find('[data-figma-status="hover"]').exists()).toBe(false)
  })

  it('renders the loading matrix with 40 members (variant + node-id text)', () => {
    const w = mountButton()
    const cells = w.findAll('.loading-matrix__variant')
    expect(cells).toHaveLength(40)
    const nodes = w.findAll('.loading-matrix__node')
    expect(nodes).toHaveLength(40)
    expect(cells[0].text()).toContain('icon=loading')
    expect(nodes[0].text()).toBe('337:12307')
  })

  it('layout: "bare" axis sections render with no .docs-demo-grid ancestor', () => {
    const w = mountButton()
    const sections = w.findAll('.docs-section')
    const basicSection = sections.find((s) => s.find('.docs-section__title').text() === 'Basic Usage')!
    expect(basicSection.find('.docs-demo-grid').exists()).toBe(false)
    expect(basicSection.find('.review-demo').exists()).toBe(true)
    // Sanity: the "grid" info sections (Figma M Coverage) DO keep the wrapper.
    const infoSection = sections.find((s) => s.find('.docs-section__title').text() === 'Figma M Coverage')!
    expect(infoSection.find('.docs-demo-grid').exists()).toBe(true)
  })
})

describe('DemoRenderer (vue) — TopBar', () => {
  function mountTopBar() {
    return mount(DemoRenderer, { props: { descriptor: topbarDescriptor, theme: 'dark', locale: 'en-US' }, global: { provide: { docsTheme: { value: 'dark' } } } })
  }

  it('renders all 4 section titles in order', () => {
    const w = mountTopBar()
    const titles = w.findAll('.docs-section__title').map((n) => n.text())
    expect(titles).toEqual(['Figma Coverage', 'Development Usage', 'Figma Members', 'Interactive: showMenu'])
  })

  it('After-Login member: meta header, real Logo component, real Icon-resolved svg', () => {
    const w = mountTopBar()
    const metas = w.findAll('.topbar-member__meta')
    const afterMeta = metas.find((m) => m.text().includes('Tag=After Login'))!
    expect(afterMeta.text()).toContain('4771:7174')
    const card = afterMeta.element.closest('.docs-demo-card')!
    // Logo is a real DS component (span.logo with inline svg via v-html), not a placeholder <img>.
    expect(card.querySelector('.logo svg')).toBeTruthy()
    expect(card.querySelector('img')).toBeNull()
    // app-launcher icon resolved via the real Icon component (svg present, not hand-copied markup).
    const gridIcon = card.querySelector('.topbar-grid-icon')
    expect(gridIcon).toBeTruthy()
    expect(gridIcon!.querySelector('svg')).toBeTruthy()
  })

  it('Before-Login member: primary CTA present, no timezone block', () => {
    const w = mountTopBar()
    const metas = w.findAll('.topbar-member__meta')
    const beforeMeta = metas.find((m) => m.text().includes('Tag=Before Login'))!
    expect(beforeMeta.text()).toContain('4771:7226')
    const card = beforeMeta.element.closest('.docs-demo-card')!
    expect(card.querySelector('.topbar-action--primary')).toBeTruthy()
    expect(card.querySelector('.timezone-block')).toBeNull()
  })

  it('Try-it card: initial readout, cycle control flips tag + right-content, text control updates title', async () => {
    const w = mountTopBar()
    const readout = () => w.find('.try-readout').text()
    expect(readout()).toContain('My Application')
    expect(readout()).toContain('After Login')

    const tryItCard = w.find('.try-readout').element.closest('.docs-demo-card')!
    expect(tryItCard.querySelector('.topbar-action--primary')).toBeNull()

    // INFRA-F148: cycle = DS Button, text = DS InputBoxLine. Assert the hand-written
    // ones are gone *and* that the DS ones still drive state — a revert fails both.
    expect(w.find('.try-controls .try-button').exists()).toBe(false)
    expect(w.find('.try-controls input.try-input').exists()).toBe(false)
    expect(w.findComponent(InputBoxLine).exists()).toBe(true)

    await w.find('.try-controls button').trigger('click')
    expect(readout()).toContain('Before Login')
    expect(tryItCard.querySelector('.topbar-action--primary')).toBeTruthy()

    await w.find('.try-controls input').setValue('Renamed App')
    expect(readout()).toContain('Renamed App')
  })

  it('Interactive: showMenu card renders 2 DS Switch controls, no native checkbox', () => {
    const w = mountTopBar()
    const sections = w.findAll('.docs-section')
    const showMenuSection = sections.find((s) => s.find('.docs-section__title').text() === 'Interactive: showMenu')!
    expect(showMenuSection.findAll('.switch').length).toBe(2)
    expect(showMenuSection.find('input[type="checkbox"]').exists()).toBe(false)
  })
})
