import {useMemo} from 'react';
import {File} from 'expo-file-system';
import {Asset, VideoAsset} from '@modules/chats/interfaces';
import {useAttachmentData} from '@modules/chats/store/zustand/useAttachments';
import {isVideoAsset, mapAssetToUrl} from '@modules/chats/utils';

interface UseMediaAssetResult {
  /** Raw asset from the Zustand store, or `undefined` if not yet registered. */
  asset: Asset | undefined;
  isVideo: boolean;
  /**
   * Display URL. For pictures: `asset.image_url`. For videos: the
   * poster `thumbnail_url`. Empty string when the asset isn't
   * available yet — saves consumers from having to dance around
   * `undefined` when building a sized URL via `getChatImage.*`.
   */
  imageUrl: string;
  /**
   * Playable URL for videos. Prefers the local `file://` URI (still on
   * device after a gallery upload that hasn't been evicted) so
   * expo-video can play without a network round-trip; falls back to
   * the remote `video_url`. `undefined` for non-video assets.
   */
  videoUrl: string | undefined;
  /** Duration in milliseconds. Videos only — `undefined` otherwise. */
  videoDurationMs: number | undefined;
}

/**
 * Single-source-of-truth derivation for any chat surface that wants to
 * render the image, thumbnail, or play a video for one `(messageId,
 * assetId)` pair. Replaces the previously-scattered pattern of:
 *
 *  ```ts
 *  const fileData = useAttachmentData(messageId, assetId);
 *  const asset = fileData?.asset;
 *  const isVideo = !!asset && isVideoAsset(asset);
 *  const url = isVideo ? asset.thumbnail_url : mapAssetToUrl(asset);
 *  const videoUrl = useVideoFileUrl(messageId, assetId);
 *  ```
 *
 * …repeated across `ImageRenderer`, `VideoRenderer`, the gallery's
 * main carousel item, and the gallery's selector strip. Folding the
 * local-file-vs-remote `videoUrl` resolution in here also retires
 * `useVideoFileUrl` — there's only one place a video playable URL is
 * derived now.
 */
export function useMediaAsset(
  messageId?: string,
  assetId?: number,
): UseMediaAssetResult {
  const fileData = useAttachmentData(messageId, assetId);
  const asset = fileData?.asset;
  const localUri = fileData?.uri;

  return useMemo(() => {
    if (!asset) {
      return {
        asset: undefined,
        isVideo: false,
        imageUrl: '',
        videoUrl: undefined,
        videoDurationMs: undefined,
      };
    }

    if (isVideoAsset(asset)) {
      const videoAsset = asset as VideoAsset;
      // `File.exists` is synchronous so this can live inside the
      // memo — no effect / state dance. The try/catch guards against
      // races where the path was registered but the file got cleaned
      // up by the OS (rare; expo-file-system throws on a stat of a
      // missing parent dir).
      let videoUrl: string | undefined = videoAsset.video_url;
      if (localUri && localUri.startsWith('file://')) {
        try {
          if (new File(localUri).exists) {
            videoUrl = localUri;
          }
        } catch {
          /* fall through to remote */
        }
      }
      return {
        asset,
        isVideo: true,
        imageUrl: videoAsset.thumbnail_url ?? '',
        videoUrl,
        videoDurationMs: videoAsset.video_duration_ms,
      };
    }

    return {
      asset,
      isVideo: false,
      imageUrl: mapAssetToUrl(asset) ?? '',
      videoUrl: undefined,
      videoDurationMs: undefined,
    };
  }, [asset, localUri]);
}
