// src/services/db/errors.db.test.ts
import { describe, it, expect } from 'vitest';
import {
  DatabaseError,
  UniqueConstraintError,
  ForeignKeyConstraintError,
  NotFoundError,
  ValidationError,
  FileUploadError,
} from './errors.db';

describe('Custom Database and Application Errors', () => {
  describe('DatabaseError', () => {
    it('should create a generic database error with a message and status', () => {
      const message = 'Generic DB Error';
      const status = 500;
      const error = new DatabaseError(message, status);

      expect(error).toBeInstanceOf(Error);
      expect(error).toBeInstanceOf(DatabaseError);
      expect(error.message).toBe(message);
      expect(error.status).toBe(status);
      expect(error.name).toBe('DatabaseError');
    });
  });

  describe('UniqueConstraintError', () => {
    it('should create an error with a default message and status 409', () => {
      const error = new UniqueConstraintError();

      expect(error).toBeInstanceOf(Error);
      expect(error).toBeInstanceOf(DatabaseError);
      expect(error).toBeInstanceOf(UniqueConstraintError);
      expect(error.message).toBe('The record already exists.');
      expect(error.status).toBe(409);
      expect(error.name).toBe('UniqueConstraintError');
    });

    it('should create an error with a custom message', () => {
      const message = 'This email is already taken.';
      const error = new UniqueConstraintError(message);
      expect(error.message).toBe(message);
    });
  });

  describe('ForeignKeyConstraintError', () => {
    it('should create an error with a default message and status 400', () => {
      const error = new ForeignKeyConstraintError();

      expect(error).toBeInstanceOf(Error);
      expect(error).toBeInstanceOf(DatabaseError);
      expect(error).toBeInstanceOf(ForeignKeyConstraintError);
      expect(error.message).toBe('The referenced record does not exist.');
      expect(error.status).toBe(400);
      expect(error.name).toBe('ForeignKeyConstraintError');
    });

    it('should create an error with a custom message', () => {
      const message = 'The specified user does not exist.';
      const error = new ForeignKeyConstraintError(message);
      expect(error.message).toBe(message);
    });
  });

  describe('NotFoundError', () => {
    it('should create an error with a default message and status 404', () => {
      const error = new NotFoundError();

      expect(error).toBeInstanceOf(Error);
      expect(error).toBeInstanceOf(DatabaseError);
      expect(error).toBeInstanceOf(NotFoundError);
      expect(error.message).toBe('The requested resource was not found.');
      expect(error.status).toBe(404);
      expect(error.name).toBe('NotFoundError');
    });

    it('should create an error with a custom message', () => {
      const message = 'Flyer with ID 999 not found.';
      const error = new NotFoundError(message);
      expect(error.message).toBe(message);
    });
  });

  describe('ValidationError', () => {
    it('should create an error with a default message, status 400, and validation errors array', () => {
      const validationIssues = [{ path: ['email'], message: 'Invalid email' }];
      const error = new ValidationError(validationIssues);

      expect(error).toBeInstanceOf(Error);
      expect(error).toBeInstanceOf(DatabaseError);
      expect(error).toBeInstanceOf(ValidationError);
      expect(error.message).toBe('The request data is invalid.');
      expect(error.status).toBe(400);
      expect(error.name).toBe('ValidationError');
      expect(error.validationErrors).toEqual(validationIssues);
    });

    it('should create an error with a custom message', () => {
      const message = 'Your input has some issues.';
      const error = new ValidationError([], message);
      expect(error.message).toBe(message);
    });
  });

  describe('FileUploadError', () => {
    it('should create an error with the correct message, name, and status 400', () => {
      const message = 'No file was uploaded.';
      const error = new FileUploadError(message);

      expect(error).toBeInstanceOf(Error);
      expect(error).toBeInstanceOf(FileUploadError);
      expect(error.message).toBe(message);
      expect(error.status).toBe(400);
      expect(error.name).toBe('FileUploadError');
    });
  });
});