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)
        })
    })
})

/**
 * PRICE CONVERSION TESTS
 * These tests verify that prices are handled correctly in CENTS
 * The API returns price_cents (e.g., 819 = R$ 8,19)
 */
describe('price conversion (cents)', () => {
    const mockItemCents: Omit<CartItem, 'quantity'> = {
        id: 'prod-cents-1',
        name: 'Paracetamol 750mg',
        activeIngredient: 'Paracetamol',
        lab: 'EMS',
        batch: 'L2025840',
        expiry: '2027-09-15',
        vendorId: 'vendor-anapolis',
        vendorName: 'Anápolis/GO',
        unitPrice: 819  // 819 cents = R$ 8,19
    }

    const mockItemCents2: Omit<CartItem, 'quantity'> = {
        id: 'prod-cents-2',
        name: 'Dipirona 500mg',
        activeIngredient: 'Dipirona',
        lab: 'Medley',
        batch: 'L2025123',
        expiry: '2026-06-30',
        vendorId: 'vendor-anapolis',
        vendorName: 'Anápolis/GO',
        unitPrice: 1299  // 1299 cents = R$ 12,99
    }

    beforeEach(() => {
        useCartStore.setState({ items: [] })
    })

    describe('storing prices in cents', () => {
        it('should store unitPrice as cents (819 = R$ 8,19)', () => {
            useCartStore.getState().addItem(mockItemCents)

            const state = useCartStore.getState()
            expect(state.items[0].unitPrice).toBe(819)
            // Verify it's NOT stored as reais (8.19)
            expect(state.items[0].unitPrice).not.toBe(8.19)
        })

        it('should preserve cents precision for subtotal calculation', () => {
            useCartStore.getState().addItem(mockItemCents, 3)

            const state = useCartStore.getState()
            const item = state.items[0]
            const subtotal = item.quantity * item.unitPrice

            // 3 * 819 = 2457 cents = R$ 24,57
            expect(subtotal).toBe(2457)
            expect(subtotal / 100).toBe(24.57)
        })
    })

    describe('cents calculations in selectors', () => {
        it('should calculate vendor total in cents', () => {
            // 819 cents * 2 = 1638 cents
            useCartStore.getState().addItem(mockItemCents, 2)
            // 1299 cents * 1 = 1299 cents
            useCartStore.getState().addItem(mockItemCents2, 1)

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

            // Total: 1638 + 1299 = 2937 cents = R$ 29,37
            expect(groups['vendor-anapolis'].total).toBe(2937)
            expect(groups['vendor-anapolis'].total / 100).toBeCloseTo(29.37)
        })

        it('should calculate cart summary total in cents', () => {
            useCartStore.getState().addItem(mockItemCents, 2)    // 1638 cents
            useCartStore.getState().addItem(mockItemCents2, 1)   // 1299 cents

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

            expect(summary.totalItems).toBe(3)
            expect(summary.totalValue).toBe(2937) // cents
            expect(summary.totalValue / 100).toBeCloseTo(29.37) // reais
        })
    })

    describe('edge cases for cents', () => {
        it('should handle single unit correctly', () => {
            useCartStore.getState().addItem(mockItemCents, 1)

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

            expect(summary.totalValue).toBe(819)
            expect(summary.totalValue / 100).toBe(8.19)
        })

        it('should handle large quantities without overflow', () => {
            useCartStore.getState().addItem(mockItemCents, 1000)

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

            // 819 * 1000 = 819000 cents = R$ 8,190.00
            expect(summary.totalValue).toBe(819000)
            expect(summary.totalValue / 100).toBe(8190)
        })

        it('should handle small cent values (R$ 0,01)', () => {
            const cheapItem: Omit<CartItem, 'quantity'> = {
                ...mockItemCents,
                id: 'cheap-1',
                unitPrice: 1  // 1 cent = R$ 0,01
            }

            useCartStore.getState().addItem(cheapItem, 10)

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

            expect(summary.totalValue).toBe(10) // 10 cents
            expect(summary.totalValue / 100).toBe(0.10)
        })
    })
})

