/**
 * Use Case: GetMediaUseCase
 *
 * Handles the business logic for retrieving media information.
 */

import type { IMediaRepository } from '../../domain/repositories/IMediaRepository';
import type { Logger, UseCaseOutputPort } from '@core/shared/application';
import { Result } from '@core/shared/application/Result';
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';

export interface GetMediaInput {
  mediaId: string;
}

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

export type GetMediaErrorCode = 'MEDIA_NOT_FOUND' | 'REPOSITORY_ERROR';

export class GetMediaUseCase {
  constructor(
    private readonly mediaRepo: IMediaRepository,
    private readonly output: UseCaseOutputPort<GetMediaResult>,
    private readonly logger: Logger,
  ) {}

  async execute(
    input: GetMediaInput,
  ): Promise<Result<void, ApplicationErrorCode<GetMediaErrorCode, { message: string }>>> {
    this.logger.info('[GetMediaUseCase] Getting media', {
      mediaId: input.mediaId,
    });

   try {
      const media = await this.mediaRepo.findById(input.mediaId);

      if (!media) {
        return Result.err<void, ApplicationErrorCode<GetMediaErrorCode, { message: string }>>({
          code: 'MEDIA_NOT_FOUND',
          details: { message: 'Media not found' },
        });
      }

      const mediaResult: GetMediaResult['media'] = {
        id: media.id,
        filename: media.filename,
        originalName: media.originalName,
        mimeType: media.mimeType,
        size: media.size,
        url: media.url.value,
        type: media.type,
        uploadedBy: media.uploadedBy,
        uploadedAt: media.uploadedAt,
      };
      
      if (media.metadata !== undefined) {
        mediaResult.metadata = media.metadata;
      }

      this.output.present({ media: mediaResult });

      return Result.ok(undefined);
    } catch (error) {
      const err = error instanceof Error ? error : new Error(String(error));
      this.logger.error('[GetMediaUseCase] Error getting media', err, {
        mediaId: input.mediaId,
      });

      return Result.err<void, ApplicationErrorCode<GetMediaErrorCode, { message: string }>>({
        code: 'REPOSITORY_ERROR',
        details: { message: err.message },
      });
    }
  }
}