import { describe, it, expect, vi, beforeEach } from 'vitest'
import { setActivePinia, createPinia } from 'pinia'

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

import { api } from '@/utils/request'
import { useSkuOriginStore } from '../sku-origin'

const mockItems = [
  { 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' },
  { id: 2, company_id: 3, sku: '0033', barcode: '6901234567891', name: 'Test SKU 2', label: 'alias', hs: '6403', created_at: '2026-04-02T00:00:00', updated_at: '2026-04-02T00:00:00' },
]

const mockPaginated = {
  items: mockItems,
  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 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,
}

describe('useSkuOriginStore', () => {
  beforeEach(() => {
    setActivePinia(createPinia())
    vi.restoreAllMocks()
  })

  describe('initial state', () => {
    it('starts with empty items and default pagination', () => {
      const store = useSkuOriginStore()

      expect(store.items).toEqual([])
      expect(store.pagination.page).toBe(1)
      expect(store.pagination.per_page).toBe(15)
      expect(store.pagination.total).toBe(0)
      expect(store.loading).toBe(false)
    })
  })

  describe('fetchItems', () => {
    it('loads data and updates state', async () => {
      vi.mocked(api.get).mockResolvedValueOnce(mockPaginated)

      const store = useSkuOriginStore()
      await store.fetchItems()

      expect(api.get).toHaveBeenCalledWith('/api/v1/sku-origins', expect.objectContaining({
        page: 1,
        per_page: 15,
      }))
      expect(store.items).toEqual(mockItems)
      expect(store.pagination.total).toBe(2)
    })

    it('passes filter params', async () => {
      vi.mocked(api.get).mockResolvedValueOnce(mockPaginated)

      const store = useSkuOriginStore()
      store.filters.sku = '0032'
      store.filters.barcode = '690'
      store.cascadeValue.company_id = 3
      await store.fetchItems()

      expect(api.get).toHaveBeenCalledWith('/api/v1/sku-origins', expect.objectContaining({
        sku: '0032',
        barcode: '690',
        company_id: 3,
      }))
    })

    it('clears data on error', async () => {
      vi.mocked(api.get).mockRejectedValueOnce(new Error('网络错误'))

      const store = useSkuOriginStore()
      await store.fetchItems()

      expect(store.items).toEqual([])
      expect(store.pagination.total).toBe(0)
    })
  })

  describe('resetFilters', () => {
    it('clears all filters and pagination', () => {
      const store = useSkuOriginStore()
      store.filters.sku = 'test'
      store.filters.barcode = '123'
      store.cascadeValue.company_id = 5
      store.pagination.page = 3

      store.resetFilters()

      expect(store.filters.sku).toBe('')
      expect(store.filters.barcode).toBe('')
      expect(store.cascadeValue.company_id).toBeUndefined()
      expect(store.pagination.page).toBe(1)
    })
  })

  describe('createItem', () => {
    it('calls API and refreshes list', async () => {
      vi.mocked(api.post).mockResolvedValueOnce({})
      vi.mocked(api.get).mockResolvedValueOnce(mockPaginated)

      const store = useSkuOriginStore()
      await store.createItem({
        company_id: 3,
        sku: 'NEW-SKU',
        barcode: '1234567890123',
        name: 'New SKU',
        label: '',
        hs: '',
        ledger: '',
      })

      expect(api.post).toHaveBeenCalledWith('/api/v1/sku-origins', expect.objectContaining({
        sku: 'NEW-SKU',
      }))
      expect(api.get).toHaveBeenCalled()
    })
  })

  describe('updateItem', () => {
    it('calls API and refreshes list', async () => {
      vi.mocked(api.put).mockResolvedValueOnce({})
      vi.mocked(api.get).mockResolvedValueOnce(mockPaginated)

      const store = useSkuOriginStore()
      await store.updateItem(1, { name: 'Updated' })

      expect(api.put).toHaveBeenCalledWith('/api/v1/sku-origins/1', { name: 'Updated' })
      expect(api.get).toHaveBeenCalled()
    })
  })

  describe('deleteItem', () => {
    it('calls API and refreshes list', async () => {
      vi.mocked(api.delete).mockResolvedValueOnce({})
      vi.mocked(api.get).mockResolvedValueOnce(mockPaginated)

      const store = useSkuOriginStore()
      await store.deleteItem(1)

      expect(api.delete).toHaveBeenCalledWith('/api/v1/sku-origins/1')
      expect(api.get).toHaveBeenCalled()
    })
  })

  describe('fetchMappings', () => {
    it('loads and caches mapping data', async () => {
      vi.mocked(api.get).mockResolvedValueOnce(mockMappings)

      const store = useSkuOriginStore()
      await store.fetchMappings(1)

      expect(api.get).toHaveBeenCalledWith('/api/v1/sku-mappings', {
        origin_sku_id: 1,
        per_page: 50,
      })
      expect(store.mappingsCache.get(1)).toEqual(mockMappings.items)
    })

    it('sets loading state correctly', async () => {
      let resolvePromise: (value: unknown) => void
      const pending = new Promise((resolve) => { resolvePromise = resolve })
      vi.mocked(api.get).mockReturnValueOnce(pending as never)

      const store = useSkuOriginStore()
      const fetchPromise = store.fetchMappings(1)

      expect(store.mappingsLoading.has(1)).toBe(true)

      resolvePromise!(mockMappings)
      await fetchPromise

      expect(store.mappingsLoading.has(1)).toBe(false)
    })

    it('caches empty array on error', async () => {
      vi.mocked(api.get).mockRejectedValueOnce(new Error('失败'))

      const store = useSkuOriginStore()
      await store.fetchMappings(99)

      expect(store.mappingsCache.get(99)).toEqual([])
    })
  })

  describe('lookup maps', () => {
    it('builds companyMap correctly', async () => {
      vi.mocked(api.get)
        .mockResolvedValueOnce(mockCompanies)
        .mockResolvedValueOnce(mockPlatforms)
        .mockResolvedValueOnce(mockStores)

      const store = useSkuOriginStore()
      await store.loadLookups()

      expect(store.companyMap.get(3)).toBe('Acme')
    })

    it('builds platformMap correctly', async () => {
      vi.mocked(api.get)
        .mockResolvedValueOnce(mockCompanies)
        .mockResolvedValueOnce(mockPlatforms)
        .mockResolvedValueOnce(mockStores)

      const store = useSkuOriginStore()
      await store.loadLookups()

      expect(store.platformMap.get(1)).toBe('Amazon')
    })

    it('builds storeMap correctly', async () => {
      vi.mocked(api.get)
        .mockResolvedValueOnce(mockCompanies)
        .mockResolvedValueOnce(mockPlatforms)
        .mockResolvedValueOnce(mockStores)

      const store = useSkuOriginStore()
      await store.loadLookups()

      expect(store.storeMap.get(101)).toBe('Store A')
    })
  })
})
