/**
 * Tests for Django Server Error
 */

import { MizanError, type FunctionErrorResponse } from '../errors'

describe('MizanError', () => {
    it('should create error with message and code', () => {
        const response: FunctionErrorResponse = {
            error: true,
            code: 'NOT_FOUND',
            message: 'Function not found',
        }

        const error = new MizanError(response)

        expect(error.message).toBe('Function not found')
        expect(error.code).toBe('NOT_FOUND')
        expect(error.name).toBe('MizanError')
    })

    it('should preserve details', () => {
        const response: FunctionErrorResponse = {
            error: true,
            code: 'VALIDATION_ERROR',
            message: 'Invalid input',
            details: {
                fields: {
                    name: ['Required', 'Too short'],
                    email: ['Invalid format'],
                },
            },
        }

        const error = new MizanError(response)

        expect(error.details).toBeDefined()
        expect(error.details?.fields?.name).toEqual(['Required', 'Too short'])
    })

    it('should preserve original response', () => {
        const response: FunctionErrorResponse = {
            error: true,
            code: 'INTERNAL_ERROR',
            message: 'Server error',
        }

        const error = new MizanError(response)

        expect(error.response).toBe(response)
    })

    describe('isValidationError', () => {
        it('should return true for validation errors', () => {
            const error = new MizanError({
                error: true,
                code: 'VALIDATION_ERROR',
                message: 'Invalid',
            })

            expect(error.isValidationError()).toBe(true)
        })

        it('should return false for other errors', () => {
            const error = new MizanError({
                error: true,
                code: 'NOT_FOUND',
                message: 'Not found',
            })

            expect(error.isValidationError()).toBe(false)
        })
    })

    describe('isAuthError', () => {
        it('should return true for unauthorized', () => {
            const error = new MizanError({
                error: true,
                code: 'UNAUTHORIZED',
                message: 'Not authenticated',
            })

            expect(error.isAuthError()).toBe(true)
        })

        it('should return true for forbidden', () => {
            const error = new MizanError({
                error: true,
                code: 'FORBIDDEN',
                message: 'Access denied',
            })

            expect(error.isAuthError()).toBe(true)
        })

        it('should return false for other errors', () => {
            const error = new MizanError({
                error: true,
                code: 'NOT_FOUND',
                message: 'Not found',
            })

            expect(error.isAuthError()).toBe(false)
        })
    })

    describe('isNotFound', () => {
        it('should return true for not found errors', () => {
            const error = new MizanError({
                error: true,
                code: 'NOT_FOUND',
                message: 'Not found',
            })

            expect(error.isNotFound()).toBe(true)
        })

        it('should return false for other errors', () => {
            const error = new MizanError({
                error: true,
                code: 'VALIDATION_ERROR',
                message: 'Invalid',
            })

            expect(error.isNotFound()).toBe(false)
        })
    })

    describe('getFieldErrors', () => {
        it('should return field errors for validation error', () => {
            const error = new MizanError({
                error: true,
                code: 'VALIDATION_ERROR',
                message: 'Invalid input',
                details: {
                    fields: {
                        name: ['Required'],
                        email: ['Invalid'],
                    },
                },
            })

            const errors = error.getFieldErrors()

            expect(errors).toEqual({
                name: ['Required'],
                email: ['Invalid'],
            })
        })

        it('should return null for non-validation errors', () => {
            const error = new MizanError({
                error: true,
                code: 'NOT_FOUND',
                message: 'Not found',
            })

            expect(error.getFieldErrors()).toBeNull()
        })

        it('should return null if no fields in details', () => {
            const error = new MizanError({
                error: true,
                code: 'VALIDATION_ERROR',
                message: 'Invalid',
                details: {},
            })

            expect(error.getFieldErrors()).toBeNull()
        })
    })

    describe('getFieldError', () => {
        it('should return first error for a field', () => {
            const error = new MizanError({
                error: true,
                code: 'VALIDATION_ERROR',
                message: 'Invalid input',
                details: {
                    fields: {
                        name: ['Required', 'Too short'],
                    },
                },
            })

            expect(error.getFieldError('name')).toBe('Required')
        })

        it('should return null for non-existent field', () => {
            const error = new MizanError({
                error: true,
                code: 'VALIDATION_ERROR',
                message: 'Invalid input',
                details: {
                    fields: {
                        name: ['Required'],
                    },
                },
            })

            expect(error.getFieldError('email')).toBeNull()
        })

        it('should return null for non-validation errors', () => {
            const error = new MizanError({
                error: true,
                code: 'NOT_FOUND',
                message: 'Not found',
            })

            expect(error.getFieldError('name')).toBeNull()
        })
    })
})
