import { useConvexAccessToken } from "@code/auth/web";
import {
  Attachment,
  AttachmentAction,
  AttachmentActions,
  AttachmentContent,
  AttachmentDescription,
  AttachmentGroup,
  AttachmentMedia,
  AttachmentTitle,
} from "@code/ui/components/attachment";
import { ImageIcon, X } from "lucide-react";
import { useEffect, useState } from "react";

import type { PendingChatImage } from "@/lib/chat/attachments";
import type { ConversationPart } from "@/lib/chat/types";

type FilePart = Extract<ConversationPart, { type: "file" }>;

const isDirectlyRenderableUrl = (url: string): boolean =>
  url.startsWith("blob:") || url.startsWith("data:");

const useAuthenticatedImageSource = (url?: string): string | undefined => {
  const resolveAccessToken = useConvexAccessToken();
  const [loaded, setLoaded] = useState<{
    readonly source: string;
    readonly url: string;
  }>();

  useEffect(() => {
    if (!url || isDirectlyRenderableUrl(url)) {
      return;
    }
    let active = true;
    let objectUrl: string | undefined;
    const load = async (): Promise<void> => {
      try {
        const accessToken = await resolveAccessToken();
        const response = await fetch(url, {
          headers: accessToken
            ? { authorization: `Bearer ${accessToken}` }
            : undefined,
        });
        if (!response.ok) {
          return;
        }
        objectUrl = URL.createObjectURL(await response.blob());
        if (active) {
          setLoaded({ source: objectUrl, url });
        }
      } catch {
        // The attachment remains represented by its filename and media type.
      }
    };
    void load();
    return () => {
      active = false;
      if (objectUrl) {
        URL.revokeObjectURL(objectUrl);
      }
    };
  }, [resolveAccessToken, url]);

  if (url && isDirectlyRenderableUrl(url)) {
    return url;
  }
  return loaded && loaded.url === url ? loaded.source : undefined;
};

const ImagePreview = ({
  alt,
  mediaType,
  url,
}: {
  readonly alt: string;
  readonly mediaType: string;
  readonly url?: string;
}) => {
  const source = useAuthenticatedImageSource(url);
  return (
    <AttachmentMedia
      variant={mediaType.startsWith("image/") ? "image" : "icon"}
    >
      {source && mediaType.startsWith("image/") ? (
        <img alt={alt} className="size-full object-cover" src={source} />
      ) : (
        <ImageIcon className="size-4" />
      )}
    </AttachmentMedia>
  );
};

export const PendingChatAttachments = ({
  images,
  onRemove,
}: {
  readonly images: readonly PendingChatImage[];
  readonly onRemove: (id: string) => void;
}) => (
  <AttachmentGroup className="max-w-full gap-2 pb-2">
    {images.map((image) => (
      <Attachment
        className="w-24 border-[#d7d3c7] bg-[#fffefa] text-[#20201d]"
        key={image.id}
        orientation="vertical"
        size="sm"
      >
        <ImagePreview
          alt={image.file.name}
          mediaType={image.file.type}
          url={image.previewUrl}
        />
        <AttachmentContent>
          <AttachmentTitle>{image.file.name}</AttachmentTitle>
        </AttachmentContent>
        <AttachmentActions>
          <AttachmentAction
            aria-label={`Remove ${image.file.name}`}
            className="bg-white/90 hover:bg-white"
            onClick={() => onRemove(image.id)}
          >
            <X className="size-3.5" />
          </AttachmentAction>
        </AttachmentActions>
      </Attachment>
    ))}
  </AttachmentGroup>
);

export const MessageAttachments = ({
  parts,
}: {
  readonly parts: readonly FilePart[];
}) => {
  if (parts.length === 0) {
    return null;
  }
  return (
    <AttachmentGroup className="mb-2 max-w-full gap-2">
      {parts.map((part, index) => {
        const title = part.filename ?? `Image ${index + 1}`;
        return (
          <Attachment
            className="min-w-0 max-w-48 border-[#d7d3c7] bg-[#fffefa] text-[#20201d]"
            key={part.id ?? `${part.mediaType}:${index}`}
            size="sm"
          >
            <ImagePreview
              alt={title}
              mediaType={part.mediaType}
              url={part.url}
            />
            <AttachmentContent>
              <AttachmentTitle>{title}</AttachmentTitle>
              <AttachmentDescription>{part.mediaType}</AttachmentDescription>
            </AttachmentContent>
          </Attachment>
        );
      })}
    </AttachmentGroup>
  );
};
