import { describe, expect, it, vi } from 'vitest';

import { AvatarGenerationRequest } from '@core/media/domain/entities/AvatarGenerationRequest';

import { AvatarGenerationRequestOrmEntity } from '../entities/AvatarGenerationRequestOrmEntity';
import { TypeOrmMediaSchemaError } from '../errors/TypeOrmMediaSchemaError';
import { AvatarGenerationRequestOrmMapper } from './AvatarGenerationRequestOrmMapper';

describe('AvatarGenerationRequestOrmMapper', () => {
  it('toDomain preserves persisted identity and uses reconstitute semantics', () => {
    const mapper = new AvatarGenerationRequestOrmMapper();

    const entity = new AvatarGenerationRequestOrmEntity();
    entity.id = '00000000-0000-4000-8000-000000000001';
    entity.userId = 'user-123';
    entity.facePhotoUrl = 'https://cdn.example.com/faces/face-1.png';
    entity.suitColor = 'red';
    entity.style = 'realistic';
    entity.status = 'completed';
    entity.generatedAvatarUrls = ['https://cdn.example.com/avatars/av-1.png', 'https://cdn.example.com/avatars/av-2.png'];
    entity.selectedAvatarIndex = 0;
    entity.errorMessage = null;
    entity.createdAt = new Date('2025-01-01T00:00:00.000Z');
    entity.updatedAt = new Date('2025-01-01T01:00:00.000Z');

    const reconstituteSpy = vi.spyOn(AvatarGenerationRequest as unknown as { reconstitute: (...args: unknown[]) => unknown }, 'reconstitute');

    const domain = mapper.toDomain(entity);

    expect(domain.id).toBe(entity.id);
    expect(domain.userId).toBe(entity.userId);
    expect(domain.facePhotoUrl.value).toBe(entity.facePhotoUrl);
    expect(domain.suitColor).toBe(entity.suitColor);
    expect(domain.status).toBe(entity.status);
    expect(domain.generatedAvatarUrls).toEqual(entity.generatedAvatarUrls);
    expect(domain.selectedAvatarIndex).toBe(entity.selectedAvatarIndex);

    expect(reconstituteSpy).toHaveBeenCalled();
  });

  it('toDomain validates persisted shape', () => {
    const mapper = new AvatarGenerationRequestOrmMapper();

    const entity = new AvatarGenerationRequestOrmEntity();
    entity.id = '00000000-0000-4000-8000-000000000001';
    entity.userId = 123 as unknown as string;
    entity.facePhotoUrl = 'https://cdn.example.com/faces/face-1.png';
    entity.suitColor = 'red';
    entity.style = 'realistic';
    entity.status = 'completed';
    entity.generatedAvatarUrls = [];
    entity.selectedAvatarIndex = null;
    entity.errorMessage = null;
    entity.createdAt = new Date('2025-01-01T00:00:00.000Z');
    entity.updatedAt = new Date('2025-01-01T01:00:00.000Z');

    try {
      mapper.toDomain(entity);
      throw new Error('expected-to-throw');
    } catch (error) {
      expect(error).toBeInstanceOf(TypeOrmMediaSchemaError);
      expect(error).toMatchObject({
        entityName: 'AvatarGenerationRequest',
        fieldName: 'userId',
        reason: 'not_string',
      });
    }
  });

  it('toOrmEntity converts domain entity to ORM entity', () => {
    const mapper = new AvatarGenerationRequestOrmMapper();

    const domain = AvatarGenerationRequest.create({
      id: '00000000-0000-4000-8000-000000000001',
      userId: 'user-123',
      facePhotoUrl: 'https://cdn.example.com/faces/face-1.png',
      suitColor: 'blue',
      style: 'cartoon',
    });

    // Simulate completion
    domain.completeWithAvatars(['https://cdn.example.com/avatars/av-1.png']);

    const entity = mapper.toOrmEntity(domain);

    expect(entity.id).toBe(domain.id);
    expect(entity.userId).toBe(domain.userId);
    expect(entity.facePhotoUrl).toBe(domain.facePhotoUrl.value);
    expect(entity.suitColor).toBe(domain.suitColor);
    expect(entity.style).toBe(domain.style);
    expect(entity.status).toBe(domain.status);
    expect(entity.generatedAvatarUrls).toEqual(domain.generatedAvatarUrls);
    expect(entity.selectedAvatarIndex).toBeNull();
    expect(entity.errorMessage).toBeNull();
  });

  it('toDomain handles optional fields correctly', () => {
    const mapper = new AvatarGenerationRequestOrmMapper();

    const entity = new AvatarGenerationRequestOrmEntity();
    entity.id = '00000000-0000-4000-8000-000000000001';
    entity.userId = 'user-123';
    entity.facePhotoUrl = 'https://cdn.example.com/faces/face-1.png';
    entity.suitColor = 'red';
    entity.style = 'realistic';
    entity.status = 'failed';
    entity.generatedAvatarUrls = [];
    entity.selectedAvatarIndex = null;
    entity.errorMessage = 'Generation failed';
    entity.createdAt = new Date('2025-01-01T00:00:00.000Z');
    entity.updatedAt = new Date('2025-01-01T01:00:00.000Z');

    const domain = mapper.toDomain(entity);

    expect(domain.errorMessage).toBe('Generation failed');
    expect(domain.selectedAvatarIndex).toBeUndefined();
  });
});
