import { Media } from '@core/media/domain/entities/Media';
import { MediaOrmEntity } from '../entities/MediaOrmEntity';
import { TypeOrmMediaSchemaError } from '../errors/TypeOrmMediaSchemaError';
import {
    assertDate,
    assertInteger,
    assertMediaType,
    assertNonEmptyString,
} from '../schema/TypeOrmMediaSchemaGuards';

export class MediaOrmMapper {
  toDomain(entity: MediaOrmEntity): Media {
    const entityName = 'Media';

    try {
      assertNonEmptyString(entityName, 'id', entity.id);
      assertNonEmptyString(entityName, 'filename', entity.filename);
      assertNonEmptyString(entityName, 'originalName', entity.originalName);
      assertNonEmptyString(entityName, 'mimeType', entity.mimeType);
      assertInteger(entityName, 'size', entity.size);
      assertNonEmptyString(entityName, 'url', entity.url);
      assertMediaType(entityName, 'type', entity.type);
      assertNonEmptyString(entityName, 'uploadedBy', entity.uploadedBy);
      assertDate(entityName, 'uploadedAt', entity.uploadedAt);
    } catch (error) {
      if (error instanceof TypeOrmMediaSchemaError) {
        throw error;
      }
      const message = error instanceof Error ? error.message : 'Invalid persisted Media';
      throw new TypeOrmMediaSchemaError({ entityName, fieldName: 'unknown', reason: 'invalid_shape', message });
    }

    try {
      const domainProps: any = {
        id: entity.id,
        filename: entity.filename,
        originalName: entity.originalName,
        mimeType: entity.mimeType,
        size: entity.size,
        url: entity.url,
        type: entity.type as 'image' | 'video' | 'document',
        uploadedBy: entity.uploadedBy,
        uploadedAt: entity.uploadedAt,
      };
  
      if (entity.metadata !== null && entity.metadata !== undefined) {
        domainProps.metadata = entity.metadata as Record<string, unknown>;
      }
  
      return Media.reconstitute(domainProps);
    } catch (error) {
      const message = error instanceof Error ? error.message : 'Invalid persisted Media';
      throw new TypeOrmMediaSchemaError({ entityName, fieldName: 'unknown', reason: 'invalid_shape', message });
    }
  }

  toOrmEntity(media: Media): MediaOrmEntity {
    const entity = new MediaOrmEntity();
    const props = media.toProps();

    entity.id = props.id;
    entity.filename = props.filename;
    entity.originalName = props.originalName;
    entity.mimeType = props.mimeType;
    entity.size = props.size;
    entity.url = props.url;
    entity.type = props.type;
    entity.uploadedBy = props.uploadedBy;
    entity.uploadedAt = props.uploadedAt;
    entity.metadata = props.metadata ?? null;

    return entity;
  }

  toStored(entity: MediaOrmEntity): Media {
    return this.toDomain(entity);
  }
}
