import { describe, it, expect, beforeEach } from 'vitest'
import { useCartStore, selectGroupedCart, selectCartSummary, CartItem } from './cartStore'

const mockItem: Omit<CartItem, 'quantity'> = {
    id: 'prod-1',
    name: 'Produto Teste',
    activeIngredient: 'Amoxicilina',
    lab: 'EMS',
    batch: 'L1001',
    expiry: '2025-12',
    vendorId: 'vendor-1',
    vendorName: 'Distribuidora Norte',
    unitPrice: 25.00
}

const mockItem2: Omit<CartItem, 'quantity'> = {
    id: 'prod-2',
    name: 'Produto Teste 2',
    activeIngredient: 'Dipirona',
    lab: 'Eurofarma',
    batch: 'L2002',
    expiry: '2026-01',
    vendorId: 'vendor-2',
    vendorName: 'Distribuidora Sul',
    unitPrice: 15.00
}

describe('cartStore', () => {
    beforeEach(() => {
        // Reset the store before each test
        useCartStore.setState({ items: [] })
    })

    describe('addItem', () => {
        it('should add an item to the cart', () => {
            const store = useCartStore.getState()
            store.addItem(mockItem)

            const state = useCartStore.getState()
            expect(state.items).toHaveLength(1)
            expect(state.items[0]).toMatchObject({ ...mockItem, quantity: 1 })
        })

        it('should add item with custom quantity', () => {
            const store = useCartStore.getState()
            store.addItem(mockItem, 5)

            const state = useCartStore.getState()
            expect(state.items[0].quantity).toBe(5)
        })

        it('should increment quantity if item already exists', () => {
            const store = useCartStore.getState()
            store.addItem(mockItem, 2)
            store.addItem(mockItem, 3)

            const state = useCartStore.getState()
            expect(state.items).toHaveLength(1)
            expect(state.items[0].quantity).toBe(5)
        })
    })

    describe('updateQuantity', () => {
        it('should update quantity of existing item', () => {
            useCartStore.getState().addItem(mockItem, 2)
            useCartStore.getState().updateQuantity('prod-1', 10)

            const state = useCartStore.getState()
            expect(state.items[0].quantity).toBe(10)
        })

        it('should not affect other items', () => {
            useCartStore.getState().addItem(mockItem, 2)
            useCartStore.getState().addItem(mockItem2, 3)
            useCartStore.getState().updateQuantity('prod-1', 10)

            const state = useCartStore.getState()
            expect(state.items[0].quantity).toBe(10)
            expect(state.items[1].quantity).toBe(3)
        })
    })

    describe('removeItem', () => {
        it('should remove item from cart', () => {
            useCartStore.getState().addItem(mockItem)
            useCartStore.getState().addItem(mockItem2)
            useCartStore.getState().removeItem('prod-1')

            const state = useCartStore.getState()
            expect(state.items).toHaveLength(1)
            expect(state.items[0].id).toBe('prod-2')
        })

        it('should handle removing non-existent item', () => {
            useCartStore.getState().addItem(mockItem)
            useCartStore.getState().removeItem('non-existent')

            const state = useCartStore.getState()
            expect(state.items).toHaveLength(1)
        })
    })

    describe('clearVendor', () => {
        it('should remove all items from a specific vendor', () => {
            const mockItemSameVendor: Omit<CartItem, 'quantity'> = {
                ...mockItem,
                id: 'prod-3',
                name: 'Outro Produto'
            }

            useCartStore.getState().addItem(mockItem)
            useCartStore.getState().addItem(mockItemSameVendor)
            useCartStore.getState().addItem(mockItem2)
            useCartStore.getState().clearVendor('vendor-1')

            const state = useCartStore.getState()
            expect(state.items).toHaveLength(1)
            expect(state.items[0].vendorId).toBe('vendor-2')
        })
    })

    describe('clearAll', () => {
        it('should remove all items from cart', () => {
            useCartStore.getState().addItem(mockItem)
            useCartStore.getState().addItem(mockItem2)
            useCartStore.getState().clearAll()

            const state = useCartStore.getState()
            expect(state.items).toHaveLength(0)
        })
    })
})

describe('selectors', () => {
    beforeEach(() => {
        useCartStore.setState({ items: [] })
    })

    describe('selectGroupedCart', () => {
        it('should group items by vendor', () => {
            useCartStore.getState().addItem(mockItem, 2)
            useCartStore.getState().addItem(mockItem2, 3)

            const state = useCartStore.getState()
            const groups = selectGroupedCart(state)

            expect(Object.keys(groups)).toHaveLength(2)
            expect(groups['vendor-1'].items).toHaveLength(1)
            expect(groups['vendor-2'].items).toHaveLength(1)
        })

        it('should calculate vendor totals correctly', () => {
            useCartStore.getState().addItem(mockItem, 2) // 2 * 25 = 50
            useCartStore.getState().addItem(mockItem2, 3) // 3 * 15 = 45

            const state = useCartStore.getState()
            const groups = selectGroupedCart(state)

            expect(groups['vendor-1'].total).toBe(50)
            expect(groups['vendor-2'].total).toBe(45)
        })

        it('should return empty object for empty cart', () => {
            const state = useCartStore.getState()
            const groups = selectGroupedCart(state)

            expect(Object.keys(groups)).toHaveLength(0)
        })
    })

    describe('selectCartSummary', () => {
        it('should calculate total items correctly', () => {
            useCartStore.getState().addItem(mockItem, 2)
            useCartStore.getState().addItem(mockItem2, 3)

            const state = useCartStore.getState()
            const summary = selectCartSummary(state)

            expect(summary.totalItems).toBe(5)
        })

        it('should calculate total value correctly', () => {
            useCartStore.getState().addItem(mockItem, 2) // 2 * 25 = 50
            useCartStore.getState().addItem(mockItem2, 3) // 3 * 15 = 45

            const state = useCartStore.getState()
            const summary = selectCartSummary(state)

            expect(summary.totalValue).toBe(95)
        })

        it('should return zeros for empty cart', () => {
            const state = useCartStore.getState()
            const summary = selectCartSummary(state)

            expect(summary.totalItems).toBe(0)
            expect(summary.totalValue).toBe(0)
        })
    })
})
