
import { useEffect, useMemo, useState } from 'react';
import { resolveAssetUrl } from '../asset_manager';
import type { Identifier } from '../types/identifiers';
import type { Document } from '../types/documents';

type AssetObject = {
  url?: string | null;
  metadata?: Record<string, unknown> | null;
  expires_at?: number | null;
  [key: string]: unknown;
};

type AssetLike = {
  id?: Identifier;
  url?: string | null;
  expires_at?: number | null;
  metadata?: Record<string, unknown> | null;
  objects?: AssetObject[];
  [key: string]: unknown;
};

type EnsureAssetUrl = (
  documentId: Identifier,
  asset: AssetLike,
  options?: { force?: boolean;[key: string]: unknown },
) => Promise<unknown>;

type GetAsset = (document: Document, assetType: string) => AssetLike | null;

type AssetViewLike = {
  url: string | null;
  metadata: Record<string, unknown> | null;
};

interface UseAssetNavigatorOptions {
  document?: Document | null;
  assetType: string;
  ensureAssetUrl?: EnsureAssetUrl | null;
  getAsset?: GetAsset;
}

interface AssetNavigatorReturn {
  document: Document | null;
  documentId: Identifier | null;
  asset: AssetLike | null;
  assetType: string;
  currentUrl: string | null;
  currentMetadata: Record<string, unknown> | null;
  isLoading: boolean;
}

export const useAssetNavigator = ({
  document,
  assetType,
  ensureAssetUrl,
  getAsset,
}: UseAssetNavigatorOptions): AssetNavigatorReturn => {
  const documentId = (document?.id ?? null) as Identifier | null;

  const asset = useMemo<AssetLike | null>(() => {
    if (!document || !getAsset) {
      return null;
    }
    return getAsset(document, assetType) || null;
  }, [document, assetType, getAsset]);

  const view = useMemo<AssetViewLike>(
    () => ({
      url: resolveAssetUrl(asset),
      metadata: (asset?.metadata as Record<string, unknown> | null) || null,
    }),
    [asset],
  );

  const currentUrl = view.url || null;
  const currentMetadata = view.metadata || null;

  const [isLoading, setIsLoading] = useState(false);

  useEffect(() => {
    if (!ensureAssetUrl || !documentId || !asset) {
      return undefined;
    }
    if (currentUrl) {
      return undefined;
    }
    let cancelled = false;
    setIsLoading(true);
    ensureAssetUrl(documentId, asset, { force: true })
      .catch(() => { })
      .finally(() => {
        if (!cancelled) {
          setIsLoading(false);
        }
      });
    return () => {
      cancelled = true;
    };
  }, [asset, currentUrl, documentId, ensureAssetUrl]);

  return {
    document,
    documentId,
    asset,
    assetType,
    currentUrl,
    currentMetadata,
    isLoading,
  };
};

export default useAssetNavigator;
