/**
 * Probe media duration from a URL or File using HTML5 media element.
 * This extracts the actual duration from the media file metadata.
 */

import { logger } from './logger';

export interface MediaDurationResult {
  duration: number;
  width?: number;
  height?: number;
}

/**
 * Probe duration from a media URL
 */
export function probeMediaDuration(
  source: string | File,
  mediaType: 'video' | 'audio',
  timeoutMs = 10000,
): Promise<MediaDurationResult | null> {
  return new Promise((resolve) => {
    const mediaElement =
      mediaType === 'video'
        ? document.createElement('video')
        : document.createElement('audio');

    let timeoutId: ReturnType<typeof setTimeout> | null = null;
    let resolved = false;

    const cleanup = () => {
      if (resolved) return;
      resolved = true;
      mediaElement.removeEventListener('loadedmetadata', onLoadedMetadata);
      mediaElement.removeEventListener('error', onError);
      if (timeoutId) clearTimeout(timeoutId);
      mediaElement.pause();
      if (mediaElement.src.startsWith('blob:')) {
        URL.revokeObjectURL(mediaElement.src);
      }
      mediaElement.removeAttribute('src');
      mediaElement.load();
    };

    const onLoadedMetadata = () => {
      const duration = mediaElement.duration;
      if (!Number.isFinite(duration) || duration <= 0) {
        logger.warn('Invalid duration from media metadata', {
          duration,
          source: typeof source === 'string' ? source : source.name,
        });
        cleanup();
        resolve(null);
        return;
      }

      const result: MediaDurationResult = { duration };

      if (mediaType === 'video' && mediaElement instanceof HTMLVideoElement) {
        if (mediaElement.videoWidth > 0) {
          result.width = mediaElement.videoWidth;
        }
        if (mediaElement.videoHeight > 0) {
          result.height = mediaElement.videoHeight;
        }
      }

      cleanup();
      resolve(result);
    };

    const onError = () => {
      logger.warn('Failed to load media for duration probe', {
        source: typeof source === 'string' ? source : source.name,
        error: mediaElement.error?.message,
      });
      cleanup();
      resolve(null);
    };

    mediaElement.addEventListener('loadedmetadata', onLoadedMetadata);
    mediaElement.addEventListener('error', onError);

    timeoutId = setTimeout(() => {
      logger.warn('Duration probe timeout', {
        source: typeof source === 'string' ? source : source.name,
        timeoutMs,
      });
      cleanup();
      resolve(null);
    }, timeoutMs);

    mediaElement.preload = 'metadata';

    if (typeof source === 'string') {
      mediaElement.src = source;
    } else {
      mediaElement.src = URL.createObjectURL(source);
    }

    mediaElement.load();
  });
}

/**
 * Check if a MIME type is a video type
 */
export function isVideoMimeType(mimeType: string | null | undefined): boolean {
  if (!mimeType) return false;
  return mimeType.startsWith('video/');
}

/**
 * Check if a MIME type is an audio type
 */
export function isAudioMimeType(mimeType: string | null | undefined): boolean {
  if (!mimeType) return false;
  return mimeType.startsWith('audio/');
}
