/**
 * Domain Entity: Media
 *
 * Represents a media file (image, video, etc.) stored in the system.
 */

import type { IEntity } from '@core/shared/domain';
import { MediaUrl } from '../value-objects/MediaUrl';

export type MediaType = 'image' | 'video' | 'document';

export interface MediaProps {
  id: string;
  filename: string;
  originalName: string;
  mimeType: string;
  size: number;
  url: string;
  type: MediaType;
  uploadedBy: string;
  uploadedAt: Date;
  metadata?: Record<string, unknown> | undefined;
}

export class Media implements IEntity<string> {
  readonly id: string;
  readonly filename: string;
  readonly originalName: string;
  readonly mimeType: string;
  readonly size: number;
  readonly url: MediaUrl;
  readonly type: MediaType;
  readonly uploadedBy: string;
  readonly uploadedAt: Date;
  readonly metadata?: Record<string, unknown> | undefined;

  private constructor(props: MediaProps) {
    this.id = props.id;
    this.filename = props.filename;
    this.originalName = props.originalName;
    this.mimeType = props.mimeType;
    this.size = props.size;
    this.url = MediaUrl.create(props.url);
    this.type = props.type;
    this.uploadedBy = props.uploadedBy;
    this.uploadedAt = props.uploadedAt;
    this.metadata = props.metadata;
  }

  static create(props: {
    id: string;
    filename: string;
    originalName: string;
    mimeType: string;
    size: number;
    url: string;
    type: MediaType;
    uploadedBy: string;
    metadata?: Record<string, unknown>;
  }): Media {
    if (!props.filename) {
      throw new Error('Filename is required');
    }
    if (!props.url) {
      throw new Error('URL is required');
    }
    if (!props.uploadedBy) {
      throw new Error('Uploaded by is required');
    }

    return new Media({
      ...props,
      uploadedAt: new Date(),
    });
  }

  static reconstitute(props: MediaProps): Media {
    return new Media(props);
  }

  toProps(): MediaProps {
    return {
      id: this.id,
      filename: this.filename,
      originalName: this.originalName,
      mimeType: this.mimeType,
      size: this.size,
      url: this.url.value,
      type: this.type,
      uploadedBy: this.uploadedBy,
      uploadedAt: this.uploadedAt,
      metadata: this.metadata,
    };
  }
}