/**
 * Unit tests for RatingEventOrmMapper
 */

import { RatingEvent } from '@core/identity/domain/entities/RatingEvent';
import { RatingDelta } from '@core/identity/domain/value-objects/RatingDelta';
import { RatingDimensionKey } from '@core/identity/domain/value-objects/RatingDimensionKey';
import { RatingEventId } from '@core/identity/domain/value-objects/RatingEventId';
import { RatingEventOrmEntity } from '../entities/RatingEventOrmEntity';
import { RatingEventOrmMapper } from './RatingEventOrmMapper';

describe('RatingEventOrmMapper', () => {
  describe('toDomain', () => {
    it('should convert ORM entity to domain entity', () => {
      const entity = new RatingEventOrmEntity();
      entity.id = '123e4567-e89b-12d3-a456-426614174000';
      entity.userId = 'user-1';
      entity.dimension = 'driving';
      entity.delta = 5.5;
      entity.weight = 1;
      entity.occurredAt = new Date('2024-01-01T10:00:00Z');
      entity.createdAt = new Date('2024-01-01T10:00:00Z');
      entity.source = { type: 'race', id: 'race-1' };
      entity.reason = { code: 'TEST', summary: 'Test event', details: {} };
      entity.visibility = { public: true, redactedFields: [] };
      entity.version = 1;

      const domain = RatingEventOrmMapper.toDomain(entity);

      expect(domain.id.value).toBe(entity.id);
      expect(domain.userId).toBe(entity.userId);
      expect(domain.dimension.value).toBe(entity.dimension);
      expect(domain.delta.value).toBe(entity.delta);
      expect(domain.weight).toBe(entity.weight);
      expect(domain.occurredAt).toEqual(entity.occurredAt);
      expect(domain.createdAt).toEqual(entity.createdAt);
      expect(domain.source).toEqual(entity.source);
      expect(domain.reason).toEqual(entity.reason);
      expect(domain.visibility).toEqual(entity.visibility);
      expect(domain.version).toBe(entity.version);
    });

    it('should handle optional weight', () => {
      const entity = new RatingEventOrmEntity();
      entity.id = '123e4567-e89b-12d3-a456-426614174000';
      entity.userId = 'user-1';
      entity.dimension = 'driving';
      entity.delta = 5.5;
      entity.occurredAt = new Date('2024-01-01T10:00:00Z');
      entity.createdAt = new Date('2024-01-01T10:00:00Z');
      entity.source = { type: 'race', id: 'race-1' };
      entity.reason = { code: 'TEST', summary: 'Test', details: {} };
      entity.visibility = { public: true, redactedFields: [] };
      entity.version = 1;

      const domain = RatingEventOrmMapper.toDomain(entity);

      expect(domain.weight).toBeUndefined();
    });
  });

  describe('toOrmEntity', () => {
    it('should convert domain entity to ORM entity', () => {
      const domain = RatingEvent.create({
        id: RatingEventId.generate(),
        userId: 'user-1',
        dimension: RatingDimensionKey.create('driving'),
        delta: RatingDelta.create(5.5),
        weight: 1,
        occurredAt: new Date('2024-01-01T10:00:00Z'),
        createdAt: new Date('2024-01-01T10:00:00Z'),
        source: { type: 'race', id: 'race-1' },
        reason: { code: 'TEST', summary: 'Test event', details: {} },
        visibility: { public: true, redactedFields: [] },
        version: 1,
      });

      const entity = RatingEventOrmMapper.toOrmEntity(domain);

      expect(entity.id).toBe(domain.id.value);
      expect(entity.userId).toBe(domain.userId);
      expect(entity.dimension).toBe(domain.dimension.value);
      expect(entity.delta).toBe(domain.delta.value);
      expect(entity.weight).toBe(domain.weight);
      expect(entity.occurredAt).toEqual(domain.occurredAt);
      expect(entity.createdAt).toEqual(domain.createdAt);
      expect(entity.source).toEqual(domain.source);
      expect(entity.reason).toEqual(domain.reason);
      expect(entity.visibility).toEqual(domain.visibility);
      expect(entity.version).toBe(domain.version);
    });

    it('should handle optional weight', () => {
      const domain = RatingEvent.create({
        id: RatingEventId.generate(),
        userId: 'user-1',
        dimension: RatingDimensionKey.create('driving'),
        delta: RatingDelta.create(5.5),
        occurredAt: new Date('2024-01-01T10:00:00Z'),
        createdAt: new Date('2024-01-01T10:00:00Z'),
        source: { type: 'race', id: 'race-1' },
        reason: { code: 'TEST', summary: 'Test', details: {} },
        visibility: { public: true, redactedFields: [] },
        version: 1,
      });

      const entity = RatingEventOrmMapper.toOrmEntity(domain);

      expect(entity.weight).toBeUndefined();
    });
  });

  describe('round-trip', () => {
    it('should preserve data through domain -> orm -> domain conversion', () => {
      const original = RatingEvent.create({
        id: RatingEventId.generate(),
        userId: 'user-1',
        dimension: RatingDimensionKey.create('driving'),
        delta: RatingDelta.create(7.5),
        weight: 0.5,
        occurredAt: new Date('2024-01-01T10:00:00Z'),
        createdAt: new Date('2024-01-01T10:00:00Z'),
        source: { type: 'race', id: 'race-1' },
        reason: { code: 'DRIVING_FINISH_STRENGTH_GAIN', summary: 'Finished 3rd', details: { position: 3 } },
        visibility: { public: true, redactedFields: [] },
        version: 1,
      });

      const entity = RatingEventOrmMapper.toOrmEntity(original);
      const restored = RatingEventOrmMapper.toDomain(entity);

      expect(restored.id.equals(original.id)).toBe(true);
      expect(restored.userId).toBe(original.userId);
      expect(restored.dimension.value).toBe(original.dimension.value);
      expect(restored.delta.value).toBe(original.delta.value);
      expect(restored.weight).toBe(original.weight);
      expect(restored.occurredAt).toEqual(original.occurredAt);
      expect(restored.createdAt).toEqual(original.createdAt);
      expect(restored.source).toEqual(original.source);
      expect(restored.reason).toEqual(original.reason);
      expect(restored.visibility).toEqual(original.visibility);
      expect(restored.version).toBe(original.version);
    });
  });
});