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

// Mocks des composables auto-importes par Nuxt (indisponibles sous happy-dom).
const mockGet = vi.hoisted(() => vi.fn())
const mockPatch = vi.hoisted(() => vi.fn())

vi.stubGlobal('useApi', () => ({
    get: mockGet,
    post: vi.fn(),
    put: vi.fn(),
    patch: mockPatch,
    delete: vi.fn(),
}))

const { useSupplier } = await import('../useSupplier')

const SAMPLE = { '@id': '/api/suppliers/85', id: 85, companyName: 'DOD59393F 862875', isArchived: false }

describe('useSupplier', () => {
    beforeEach(() => {
        mockGet.mockReset()
        mockPatch.mockReset()
        mockGet.mockResolvedValue(SAMPLE)
        mockPatch.mockResolvedValue({ ...SAMPLE, isArchived: true })
    })

    it('charge le detail via GET /suppliers/{id} en Hydra, sans toast', async () => {
        const { supplier, load } = useSupplier(85)
        await load()

        expect(mockGet).toHaveBeenCalledWith(
            '/suppliers/85',
            {},
            expect.objectContaining({
                headers: { Accept: 'application/ld+json' },
                toast: false,
            }),
        )
        expect(supplier.value).toEqual(SAMPLE)
    })

    it('bascule loading pendant le chargement et le retombe a false', async () => {
        const { loading, load } = useSupplier(85)
        const promise = load()
        expect(loading.value).toBe(true)
        await promise
        expect(loading.value).toBe(false)
    })

    it('marque error et laisse supplier null si le GET echoue (404...)', async () => {
        mockGet.mockRejectedValueOnce(new Error('not found'))
        const { supplier, error, load } = useSupplier(99)
        await load()
        expect(error.value).toBe(true)
        expect(supplier.value).toBeNull()
    })

    it('archive() PATCHe { isArchived: true } sans toast puis RECHARGE le detail complet', async () => {
        // 1er GET = chargement initial, 2e GET = rechargement post-archivage.
        mockGet.mockResolvedValueOnce(SAMPLE)
        mockGet.mockResolvedValueOnce({ ...SAMPLE, isArchived: true })
        const { supplier, load, archive } = useSupplier(85)
        await load()
        await archive()

        expect(mockPatch).toHaveBeenCalledWith(
            '/suppliers/85',
            { isArchived: true },
            expect.objectContaining({ toast: false }),
        )
        // Le detail est re-fetch (le PATCH ne renvoie pas l'embed complet).
        expect(mockGet).toHaveBeenCalledTimes(2)
        expect(supplier.value?.isArchived).toBe(true)
    })

    it('restore() PATCHe { isArchived: false } (payload isArchived SEUL)', async () => {
        const { load, restore } = useSupplier(85)
        await load()
        await restore()

        expect(mockPatch).toHaveBeenCalledWith(
            '/suppliers/85',
            { isArchived: false },
            expect.objectContaining({ toast: false }),
        )
    })

    it('propage l\'erreur (ex: 403 sans permission archive, 409 conflit homonyme) au lieu de l\'avaler', async () => {
        const forbidden = { response: { status: 403 } }
        mockPatch.mockRejectedValueOnce(forbidden)
        const { load, archive } = useSupplier(85)
        await load()
        await expect(archive()).rejects.toBe(forbidden)
    })
})
