let jobsApi: any
let companiesApi: any
let usersApi: any
let adminCompaniesApi: any

// Mock config module to avoid initConfig fetching
jest.mock('../config', () => ({
    initConfig: jest.fn().mockResolvedValue({}),
    getApiUrl: jest.fn().mockReturnValue('http://test-api.com'),
    getBackofficeUrl: jest.fn().mockReturnValue('http://test-backoffice.com'),
    getConfig: jest.fn().mockReturnValue({}),
}))

beforeEach(() => {
    jest.clearAllMocks()

    // We don't need to reset modules or re-require if we mock the config imports
    // But api.ts might have been loaded. 
    // Since we use jest.mock at top level (hoisted), api.ts should use the mock.

    jobsApi = require('../api').jobsApi
    companiesApi = require('../api').companiesApi
    usersApi = require('../api').usersApi
    adminCompaniesApi = require('../api').adminCompaniesApi

    global.fetch = jest.fn()
})

afterEach(() => {
    jest.clearAllMocks()
})



describe('API Client', () => {
    describe('jobsApi', () => {
        it('should fetch jobs with correct parameters', async () => {
            const mockJobs = {
                data: [{ id: 1, title: 'Dev Job' }],
                pagination: { total: 1 }
            }
                ; (global.fetch as jest.Mock).mockResolvedValueOnce({
                    ok: true,
                    json: async () => mockJobs,
                })

            const response = await jobsApi.list({ page: 1, limit: 10, companyId: '5' })

            expect(global.fetch).toHaveBeenCalledWith(
                'http://test-api.com/api/v1/jobs?page=1&limit=10&companyId=5',
                expect.objectContaining({
                    headers: expect.objectContaining({
                        'Content-Type': 'application/json'
                    })
                })
            )
            expect(response).toEqual(mockJobs)
        })

        it('should handle API errors correctly', async () => {
            ; (global.fetch as jest.Mock).mockResolvedValueOnce({
                ok: false,
                status: 404,
                json: async () => ({ message: 'Not Found' }),
            })

            await expect(jobsApi.list({ page: 1, limit: 10 })).rejects.toThrow('Not Found')
        })

        it('should build URL with all filter parameters', async () => {
            ; (global.fetch as jest.Mock).mockResolvedValueOnce({
                ok: true,
                json: async () => ({ data: [], pagination: {} }),
            })

            await jobsApi.list({
                page: 1,
                limit: 20,
                q: 'developer',
                location: 'sp',
                type: 'full-time',
                workMode: 'remote'
            })

            const calledUrl = (global.fetch as jest.Mock).mock.calls[0][0]
            expect(calledUrl).toContain('page=1')
            expect(calledUrl).toContain('limit=20')
            expect(calledUrl).toContain('q=developer')
            expect(calledUrl).toContain('location=sp')
            expect(calledUrl).toContain('workMode=remote')
        })
    })

    describe('companiesApi', () => {
        it('should create company correctly', async () => {
            const mockCompany = { id: '123', name: 'Test Corp' }
                ; (global.fetch as jest.Mock).mockResolvedValueOnce({
                    ok: true,
                    json: async () => mockCompany,
                })

            const newCompany = { name: 'Test Corp', slug: 'test-corp' }
            await adminCompaniesApi.create(newCompany)

            expect(global.fetch).toHaveBeenCalledWith(
                'http://test-api.com/api/v1/companies',
                expect.objectContaining({
                    method: 'POST',
                    body: JSON.stringify(newCompany)
                })
            )
        })
    })

    describe('usersApi', () => {
        it('should list users with pagination', async () => {
            ; (global.fetch as jest.Mock).mockResolvedValueOnce({
                ok: true,
                json: async () => ({ data: [], pagination: { total: 0 } }),
            })

            await usersApi.list({ page: 1, limit: 10 })

            expect(global.fetch).toHaveBeenCalledWith(
                'http://test-api.com/api/v1/users?page=1&limit=10',
                expect.any(Object)
            )
        })
    })

    describe('URL Construction', () => {
        it('should not have double /api/v1 in URL', async () => {
            ; (global.fetch as jest.Mock).mockResolvedValueOnce({
                ok: true,
                json: async () => ({ data: [], pagination: {} }),
            })

            await usersApi.list({ page: 1, limit: 10 })

            const calledUrl = (global.fetch as jest.Mock).mock.calls[0][0]
            // Should NOT contain /api/v1/api/v1
            expect(calledUrl).not.toContain('/api/v1/api/v1')
            // Should contain exactly one /api/v1
            expect(calledUrl).toBe('http://test-api.com/api/v1/users?page=1&limit=10')
        })
    })

    describe('adminJobsApi', () => {
        it('should list jobs for moderation', async () => {
            ; (global.fetch as jest.Mock).mockResolvedValue({ ok: true, json: async () => ({ data: [], pagination: {} }) });
            const api = require('../api').adminJobsApi
            await api.list({ status: 'pending' })
            expect(global.fetch).toHaveBeenCalledWith(
                expect.stringContaining('/jobs/moderation?status=pending'),
                expect.anything()
            )
        })
    })

    describe('adminTagsApi', () => {
        it('should list tags', async () => {
            ; (global.fetch as jest.Mock).mockResolvedValue({ ok: true, json: async () => ({ data: [], pagination: {} }) });
            const api = require('../api').adminTagsApi
            await api.list()
            expect(global.fetch).toHaveBeenCalledWith(
                expect.stringContaining('/tags'),
                expect.anything()
            )
        })
    })

    describe('notificationsApi', () => {
        it('should list notifications', async () => {
            ; (global.fetch as jest.Mock).mockResolvedValue({ ok: true, json: async () => [] });
            const api = require('../api').notificationsApi
            await api.list()
            expect(global.fetch).toHaveBeenCalledWith(
                expect.stringContaining('/notifications'),
                expect.anything()
            )
        })
    })

    describe('ticketsApi', () => {
        it('should list tickets', async () => {
            ; (global.fetch as jest.Mock).mockResolvedValue({ ok: true, json: async () => [] });
            const api = require('../api').ticketsApi
            await api.list()
            expect(global.fetch).toHaveBeenCalledWith(
                expect.stringContaining('/support/tickets'),
                expect.anything()
            )
        })
    })

    describe('backofficeApi', () => {
        it('should get admin stats', async () => {
            ; (global.fetch as jest.Mock).mockResolvedValue({ ok: true, json: async () => ({}) });
            const api = require('../api').backofficeApi
            // Mock config for backoffice usage if needed, though we mocked getBackofficeUrl
            await api.admin.getStats()
            expect(global.fetch).toHaveBeenCalledWith(
                expect.stringContaining('/admin/stats'),
                expect.anything()
            )
        })
    })

    describe('Error Handling', () => {
        it('should throw error with message from API', async () => {
            ; (global.fetch as jest.Mock).mockResolvedValueOnce({
                ok: false,
                status: 401,
                json: async () => ({ message: 'Unauthorized' }),
            })

            await expect(usersApi.list({ page: 1, limit: 10 })).rejects.toThrow('Unauthorized')
        })

        it('should throw generic error when no message', async () => {
            ; (global.fetch as jest.Mock).mockResolvedValueOnce({
                ok: false,
                status: 500,
                json: async () => ({}),
            })

            await expect(usersApi.list({ page: 1, limit: 10 })).rejects.toThrow('Request failed with status 500')
        })
    })
})

