import { resolveDocumentAssetUrl, resolveAssetUrl } from '../asset_manager';
import type {
  GetAsset as AssetManagerGetAsset,
} from '../asset_manager';
import type {
  Document,
  DocumentVersion,
} from '../types/documents';
import type { AssetLike } from '../types/assets';

export type { Document, DocumentVersion, AssetLike };

export type EnsurePreviewData = (id: string) => Promise<Document | null>;
export type EnsureAssetUrl = (
  id: string,
  asset: AssetLike,
  options?: { force?: boolean },
) => Promise<AssetLike | null>;
export type GetDocumentAsset = AssetManagerGetAsset;

interface ResolveOcrTextUrlOptions {
  document: Document | null;
  ensurePreviewData?: EnsurePreviewData;
  getDocumentAsset?: GetDocumentAsset;
  ensureAssetUrl?: EnsureAssetUrl;
}

const pickAsset = (doc?: Document | null, getDocumentAsset?: GetDocumentAsset): AssetLike | null => {
  if (!doc || !getDocumentAsset) {
    return null;
  }
  return getDocumentAsset(doc, 'ocr-text') || null;
};

export async function resolveOcrTextUrl({
  document,
  ensurePreviewData,
  getDocumentAsset,
  ensureAssetUrl,
}: ResolveOcrTextUrlOptions): Promise<string | null> {
  if (!document?.id) {
    return null;
  }

  let docRef = document;
  let asset = pickAsset(docRef, getDocumentAsset);

  if (!asset && ensurePreviewData) {
    const refreshed = await ensurePreviewData(docRef.id);
    if (refreshed) {
      docRef = refreshed;
    }
    asset = pickAsset(docRef, getDocumentAsset);
  }

  if (!asset) {
    return null;
  }

  const baseUrl = resolveAssetUrl(asset);
  const hasUrl = Boolean(baseUrl);

  let entry: AssetLike = asset;
  if (ensureAssetUrl) {
    const ensureOptions = { force: !hasUrl };
    const ensured = await ensureAssetUrl(docRef.id!, asset, ensureOptions);
    if (ensured) {
      entry = ensured;
    }
  }

  const directUrl = resolveAssetUrl(entry);
  if (directUrl) {
    return directUrl;
  }

  return (
    resolveDocumentAssetUrl(docRef, 'ocr-text', {
      ensureAssetUrl,
      getAsset: getDocumentAsset,
      ensureOptions: { force: true },
    }) || null
  );
}

export async function openOcrTextInNewTab(options: ResolveOcrTextUrlOptions): Promise<boolean> {
  const popup = window.open('', '_blank');
  const popupAvailable = Boolean(popup);

  if (popupAvailable) {
    try {
      popup.opener = null;
    } catch {
      /* ignore */
    }
  }

  try {
    const url = await resolveOcrTextUrl(options);
    if (!url) {
      if (popupAvailable) {
        popup.close();
      }
      return false;
    }

    if (popupAvailable) {
      try {
        popup.location.replace(url);
      } catch {
        try {
          popup.location.href = url;
        } catch (secondError) {
          popup.close();
          throw secondError;
        }
      }
    } else {
      const finalWindow = window.open(url, '_blank');
      if (finalWindow) {
        try {
          finalWindow.opener = null;
        } catch {
          /* ignore */
        }
      }
    }

    return true;
  } catch (error) {
    if (popupAvailable) {
      popup.close();
    }
    throw error;
  }
}
