'use client';

import { useCallback, useEffect, useRef, useState } from 'react';

import { supportApi } from './supportApi';

/**
 * Blob object URL for an attachment, or `undefined` while it loads / on failure.
 *
 * Chat attachments cannot be rendered with a direct `<img src={a.url}>`. The API
 * guard takes the bearer token from the `Authorization` header and has no cookie
 * fallback, and an `<img>` request cannot carry that header — a direct src is an
 * unavoidable 401. So the bytes are fetched through the authenticated client and
 * handed to the browser as an object URL.
 *
 * The URL is revoked on unmount and whenever the attachment changes, so a thread
 * scrolled through hundreds of images doesn't pin all of them in memory.
 */
export function useAttachmentObjectUrl(relativeUrl: string): {
  src?: string;
  failed: boolean;
} {
  const [src, setSrc] = useState<string>();
  const [failed, setFailed] = useState(false);

  useEffect(() => {
    let cancelled = false;
    let created: string | undefined;

    setSrc(undefined);
    setFailed(false);

    supportApi
      .fetchAttachment(relativeUrl)
      .then((blob) => {
        // The component may have unmounted mid-flight; creating a URL then would
        // leak it, since the cleanup below has already run.
        if (cancelled) return;
        created = URL.createObjectURL(blob);
        setSrc(created);
      })
      .catch(() => {
        if (!cancelled) setFailed(true);
      });

    return () => {
      cancelled = true;
      if (created) URL.revokeObjectURL(created);
    };
  }, [relativeUrl]);

  return { src, failed };
}

/**
 * On-demand variant for files that aren't previewed inline (documents): fetch
 * only when the user actually opens one, rather than pulling every attachment in
 * the thread down just to render a filename row.
 *
 * Holds a single slot — opening another file revokes the previous URL, as does
 * unmounting.
 */
export function useLazyAttachmentObjectUrl(): (relativeUrl: string) => Promise<string> {
  const current = useRef<string>();

  useEffect(
    () => () => {
      if (current.current) URL.revokeObjectURL(current.current);
    },
    [],
  );

  return useCallback(async (relativeUrl: string) => {
    const blob = await supportApi.fetchAttachment(relativeUrl);
    if (current.current) URL.revokeObjectURL(current.current);
    current.current = URL.createObjectURL(blob);
    return current.current;
  }, []);
}
