import { HttpStatus } from '@nestjs/common';
import { describe, expect, it } from 'vitest';
import {
  ConflictException,
  DomainException,
  ForbiddenException,
  NotFoundException,
  UnauthorizedException,
  ValidationException,
} from '../domain-exception';
import { ErrorCode } from '../error-codes';

describe('DomainException', () => {
  it('should create with error code and message', () => {
    const ex = new DomainException(ErrorCode.INTERNAL_ERROR, 'Something failed');
    expect(ex.errorCode).toBe(ErrorCode.INTERNAL_ERROR);
    expect(ex.message).toBe('Something failed');
    expect(ex.getStatus()).toBe(HttpStatus.INTERNAL_SERVER_ERROR);
  });

  it('should accept details', () => {
    const ex = new DomainException(ErrorCode.VALIDATION_FAILED, 'Invalid', HttpStatus.BAD_REQUEST, {
      field: 'email',
    });
    expect(ex.details).toEqual({ field: 'email' });
  });
});

describe('NotFoundException', () => {
  it('should format message with entity and id', () => {
    const ex = new NotFoundException('User', '123');
    expect(ex.message).toBe("User with id '123' not found");
    expect(ex.getStatus()).toBe(HttpStatus.NOT_FOUND);
    expect(ex.errorCode).toBe(ErrorCode.NOT_FOUND);
  });

  it('should format message without id', () => {
    const ex = new NotFoundException('Course');
    expect(ex.message).toBe('Course not found');
  });
});

describe('ValidationException', () => {
  it('should be BAD_REQUEST with details', () => {
    const ex = new ValidationException('Invalid input', { field: 'name' });
    expect(ex.getStatus()).toBe(HttpStatus.BAD_REQUEST);
    expect(ex.errorCode).toBe(ErrorCode.VALIDATION_FAILED);
    expect(ex.details).toEqual({ field: 'name' });
  });
});

describe('ConflictException', () => {
  it('should be CONFLICT', () => {
    const ex = new ConflictException('Already exists');
    expect(ex.getStatus()).toBe(HttpStatus.CONFLICT);
    expect(ex.errorCode).toBe(ErrorCode.CONFLICT);
  });
});

describe('UnauthorizedException', () => {
  it('should default message', () => {
    const ex = new UnauthorizedException();
    expect(ex.message).toBe('Unauthorized');
    expect(ex.getStatus()).toBe(HttpStatus.UNAUTHORIZED);
  });
});

describe('ForbiddenException', () => {
  it('should default message', () => {
    const ex = new ForbiddenException();
    expect(ex.message).toBe('Forbidden');
    expect(ex.getStatus()).toBe(HttpStatus.FORBIDDEN);
  });
});
