import { DataAccessError } from './data-access.error';

/**
 * Test suite for DataAccessError class.
 * Validates the functionality of the base error class used for structured error handling.
 */
describe('DataAccessError', () => {
  /**
   * Tests basic error functionality without additional data
   */
  describe('Basic Error without Data', () => {
    class TestError extends DataAccessError<'TEST_ERROR'> {
      constructor(message: string) {
        super('TEST_ERROR', message, undefined);
      }
    }

    it('should create an error with a code and message', () => {
      // Arrange & Act
      const error = new TestError('Test message');

      // Assert
      expect(error).toBeInstanceOf(Error);
      expect(error).toBeInstanceOf(DataAccessError);
      expect(error.code).toBe('TEST_ERROR');
      expect(error.message).toBe('Test message');
      expect(error.data).toBeUndefined();
    });
  });

  /**
   * Tests error functionality with additional data, ensuring type safety
   * and proper data handling
   */
  describe('Error with Data', () => {
    interface ValidationData {
      field: string;
      issues: string[];
    }

    class ValidationError extends DataAccessError<
      'VALIDATION_ERROR',
      ValidationData
    > {
      constructor(message: string, data: ValidationData) {
        super('VALIDATION_ERROR', message, data);
      }
    }

    it('should create an error with code, message, and data', () => {
      // Arrange
      const validationData: ValidationData = {
        field: 'email',
        issues: ['Invalid format', 'Required field'],
      };

      // Act
      const error = new ValidationError('Validation failed', validationData);

      // Assert
      expect(error).toBeInstanceOf(Error);
      expect(error).toBeInstanceOf(DataAccessError);
      expect(error.code).toBe('VALIDATION_ERROR');
      expect(error.message).toBe('Validation failed');
      expect(error.data).toEqual(validationData);
    });

    it('should maintain data type safety', () => {
      // Arrange
      const validationData: ValidationData = {
        field: 'username',
        issues: ['Too short'],
      };

      // Act
      const error = new ValidationError('Validation failed', validationData);

      // Assert
      expect(error.data.field).toBe('username');
      expect(error.data.issues).toContain('Too short');
    });
  });

  /**
   * Tests type safety enforcement for error codes and data
   */
  describe('Error Type Safety', () => {
    it('should ensure type safety for error codes', () => {
      class TypedError extends DataAccessError<'TYPE_ERROR'> {
        constructor() {
          super('TYPE_ERROR', 'Type error message', undefined);
        }
      }

      const error = new TypedError();
      const errorCode: 'TYPE_ERROR' = error.code; // TypeScript will error if type safety fails
      expect(errorCode).toBe('TYPE_ERROR');
    });
  });
});
