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 mockMappings = {
  items: [
    { id: 1, 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, bundled: true, note: null, created_at: '2026-04-01T00:00:00', updated_at: '2026-04-01T00:00:00' },
    { id: 2, company_id: 3, platform_id: 1, store_id: null, origin_sku: '0033', origin_sku_id: 2, platform_outer_sku: 'AMZ-0033', platform_product_id: 'ITEM-002', enabled: true, bundled: false, note: null, created_at: '2026-04-01T00:00:00', updated_at: '2026-04-01T00:00:00' },
  ],
  total: 2,
  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 mockSkuOrigins = {
  items: [{ id: 1, company_id: 3, sku: '0032', name: 'Test SKU' }],
  total: 1,
  page: 1,
  per_page: 100,
}

function setupApiMocks() {
  vi.mocked(api.get).mockImplementation((url: string) => {
    if (url === '/api/v1/sku-mappings') return Promise.resolve(mockMappings) 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-origins') return Promise.resolve(mockSkuOrigins) as never
    return Promise.resolve({ items: [], total: 0, page: 1, per_page: 15 }) as never
  })
}

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

  const stubs = {
    SearchOutlined: { template: '<span />' },
    ReloadOutlined: { template: '<span />' },
    PlusOutlined: { template: '<span />' },
    EditOutlined: { template: '<span />' },
    DeleteOutlined: { template: '<span />' },
    ThunderboltOutlined: { template: '<span />' },
    QuestionCircleOutlined: { 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: SkuMappingsPage } = await import('../index.vue')

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

  it('P1: renders page title as SKU 连接管理', async () => {
    await mountPage()

    expect(wrapper.text()).toContain('SKU 连接管理')
    expect(wrapper.text()).not.toContain('SKU 映射管理')
  }, 15000)

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

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

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

    const html = wrapper.html()
    expect(html).toContain('AMZ-0032')
    expect(html).toContain('ITEM-001')
  })

  it('P4: create button uses 连接 terminology', 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(false)
  })

  it('P5: platform_product_id has optional placeholder', async () => {
    await mountPage()

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

    // Modal teleports to document.body
    const bodyHtml = document.body.innerHTML
    expect(bodyHtml).toContain('可选')
  })

  it('P6: search and reset buttons work', 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('P7: renders 组合商品 column with blue/default tags per bundled', async () => {
    await mountPage()

    const html = wrapper.html()
    expect(html).toContain('组合商品')
    const rows = wrapper.findAll('tbody tr')
    const bundledRow = rows.find((r) => r.text().includes('AMZ-0032'))
    const plainRow = rows.find((r) => r.text().includes('AMZ-0033'))
    expect(bundledRow?.html()).toMatch(/ant-tag-blue[^>]*>\s*是/)
    expect(plainRow?.html()).toMatch(/ant-tag[^>]*>\s*否/)
    expect(plainRow?.html()).not.toMatch(/ant-tag-blue[^>]*>\s*否/)
  })

  it('P8: form contains bundled Switch defaulted to off on create', async () => {
    await mountPage()

    const newBtn = wrapper.findAll('.ant-btn').find((b) => b.text().includes('新建连接'))
    await newBtn?.trigger('click')
    await flushPromises()
    await nextTick()

    const bodyHtml = document.body.innerHTML
    expect(bodyHtml).toContain('组合商品')
    const switches = document.body.querySelectorAll('.ant-switch')
    const bundledSwitch = Array.from(switches).find((s) => {
      const label = s.closest('.ant-form-item')?.querySelector('.ant-form-item-label')
      return label?.textContent?.includes('组合商品')
    })
    expect(bundledSwitch).toBeTruthy()
    expect(bundledSwitch?.classList.contains('ant-switch-checked')).toBe(false)
  })

  it('P9: origin_sku_id required validation triggers error on empty submit', async () => {
    await mountPage()

    const newBtn = wrapper.findAll('.ant-btn').find((b) => b.text().includes('新建连接'))
    await newBtn?.trigger('click')
    await flushPromises()
    await nextTick()

    const okBtn = Array.from(document.body.querySelectorAll('.ant-modal-footer .ant-btn')).find(
      (b) => {
        const t = (b as HTMLElement).textContent ?? ''
        return t.includes('确 定') || t.includes('确定') || t.includes('OK')
      },
    ) as HTMLElement | undefined
    okBtn?.click()
    await flushPromises()
    await nextTick()

    await vi.waitFor(
      () => {
        expect(document.body.innerHTML).toContain('请选择内部 SKU')
      },
      { timeout: 8000, interval: 100 },
    )
  }, 15000)

  it('P10: filter area exposes bundled dropdown with 是/否 options', async () => {
    await mountPage()

    const formItemLabels = wrapper.findAll('.filter-form .ant-form-item-label label')
    const bundledLabel = formItemLabels.find((l) => l.text().includes('组合商品'))
    expect(bundledLabel).toBeTruthy()
  })
})
