import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
import { mount, flushPromises } from '@vue/test-utils'
import { nextTick } from 'vue'
import { setActivePinia, createPinia } from 'pinia'

Object.defineProperty(window, 'matchMedia', {
  writable: true,
  value: (query: string) => ({
    matches: false,
    media: query,
    onchange: null,
    addListener: () => {},
    removeListener: () => {},
    addEventListener: () => {},
    removeEventListener: () => {},
    dispatchEvent: () => false,
  }),
})

vi.mock('@/utils/request', () => ({
  api: {
    get: vi.fn(),
    post: vi.fn(),
    put: vi.fn(),
    delete: vi.fn(),
  },
}))

import { api } from '@/utils/request'

const mockPaginated = {
  items: [
    { id: 1, company_id: 3, sku: '0032', barcode: '6901234567890', name: 'Test SKU', label: null, hs: null, created_at: '2026-04-01T00:00:00', updated_at: '2026-04-01T00:00:00' },
  ],
  total: 1,
  page: 1,
  per_page: 15,
}

const mockCompanies = [{ id: 3, name: 'Acme Corp', label: 'Acme' }]
const mockPlatforms = [{ id: 1, name: 'Amazon', label: null }]
const mockStores = [{ id: 101, company_id: 3, platform_id: 1, name: 'Store A', label: null }]

const mockMappings = {
  items: [
    { id: 10, company_id: 3, platform_id: 1, store_id: null, origin_sku: '0032', origin_sku_id: 1, platform_outer_sku: 'AMZ-0032', platform_product_id: 'ITEM-001', enabled: true, note: null, created_at: '2026-04-01T00:00:00', updated_at: '2026-04-01T00:00:00' },
  ],
  total: 1,
  page: 1,
  per_page: 50,
}

function setupApiMocks() {
  vi.mocked(api.get).mockImplementation((url: string) => {
    if (url === '/api/v1/sku-origins') return Promise.resolve(mockPaginated) as never
    if (url === '/api/v1/companies') return Promise.resolve(mockCompanies) as never
    if (url === '/api/v1/platforms') return Promise.resolve(mockPlatforms) as never
    if (url === '/api/v1/stores') return Promise.resolve(mockStores) as never
    if (url === '/api/v1/sku-mappings') return Promise.resolve(mockMappings) as never
    return Promise.resolve({ items: [], total: 0, page: 1, per_page: 15 }) as never
  })
}

describe('SkuOriginsPage', () => {
  let wrapper: ReturnType<typeof mount>

  const stubs = {
    SearchOutlined: { template: '<span />' },
    ReloadOutlined: { template: '<span />' },
    PlusOutlined: { template: '<span />' },
    EditOutlined: { template: '<span />' },
    DeleteOutlined: { template: '<span />' },
    LinkOutlined: { template: '<span />' },
    CascadeFilter: { template: '<div class="cascade-stub" />' },
  }

  beforeEach(() => {
    setActivePinia(createPinia())
    vi.restoreAllMocks()
    document.body.innerHTML = ''
  })

  afterEach(() => {
    wrapper?.unmount()
    document.body.innerHTML = ''
  })

  async function mountPage() {
    setupApiMocks()

    const { default: SkuOriginsPage } = await import('../index.vue')

    wrapper = mount(SkuOriginsPage, {
      attachTo: document.body,
      global: { stubs },
    })
    await flushPromises()
    await nextTick()
  }

  it('P1: renders page title and action buttons', async () => {
    await mountPage()

    expect(wrapper.text()).toContain('内部 SKU 管理')
    expect(wrapper.text()).toContain('新建 SKU')
  }, 15000)

  it('P2: calls fetchItems on mount', async () => {
    await mountPage()

    expect(api.get).toHaveBeenCalledWith('/api/v1/sku-origins', expect.any(Object))
  })

  it('P3: renders table with sku data', async () => {
    await mountPage()

    const html = wrapper.html()
    expect(html).toContain('0032')
    expect(html).toContain('Test SKU')
  })

  it('P4: search and reset buttons exist', async () => {
    await mountPage()

    const buttons = wrapper.findAll('.ant-btn')
    const buttonTexts = buttons.map((b) => b.text())
    expect(buttonTexts.some((t) => t.includes('搜索'))).toBe(true)
    expect(buttonTexts.some((t) => t.includes('重置'))).toBe(true)
  })

  it('P5: barcode field is required in create modal', async () => {
    await mountPage()

    // Open create modal
    const newBtn = wrapper.findAll('.ant-btn').find((b) => b.text().includes('新建 SKU'))
    await newBtn?.trigger('click')
    await flushPromises()
    await nextTick()

    // Modal teleports to document.body
    const bodyHtml = document.body.innerHTML
    expect(bodyHtml).toContain('条形码 / GTIN 编码')
  })

  it('P6: new link button exists in action column', async () => {
    await mountPage()

    const html = wrapper.html()
    expect(html).toContain('新建链接')
  })

  it('P7: terminology uses 链接 not 映射', async () => {
    await mountPage()

    const html = wrapper.html()
    expect(html).toContain('链接')
    expect(html).not.toContain('映射')
  })
})
