import { useEffect, useRef, useState } from "react";

import { MAX_CHAT_IMAGES, validateChatImage } from "@/lib/chat/attachments";
import type { PendingChatImage } from "@/lib/chat/attachments";

const generateImageId = (): string =>
  globalThis.crypto?.randomUUID?.() ??
  `${Date.now()}-${Math.random().toString(16).slice(2)}`;

export const useChatImages = () => {
  const [images, setImages] = useState<PendingChatImage[]>([]);
  const [error, setError] = useState<string>();
  const previewUrls = useRef(new Set<string>());

  useEffect(
    () => () => {
      for (const previewUrl of previewUrls.current) {
        URL.revokeObjectURL(previewUrl);
      }
    },
    []
  );

  const addFiles = (files: FileList | null) => {
    if (!files) {
      return;
    }
    setError(undefined);
    setImages((current) => {
      const remaining = MAX_CHAT_IMAGES - current.length;
      if (remaining <= 0) {
        setError(`Attach up to ${MAX_CHAT_IMAGES} images`);
        return current;
      }
      const next = [...current];
      for (const file of [...files].slice(0, remaining)) {
        const validation = validateChatImage(file);
        if (!validation.accepted) {
          setError(validation.message);
          continue;
        }
        const previewUrl = URL.createObjectURL(file);
        previewUrls.current.add(previewUrl);
        next.push({
          file,
          id: generateImageId(),
          previewUrl,
        });
      }
      if (files.length > remaining) {
        setError(`Attach up to ${MAX_CHAT_IMAGES} images`);
      }
      return next;
    });
  };

  const remove = (id: string) => {
    setImages((current) => {
      const removed = current.find((image) => image.id === id);
      if (removed) {
        URL.revokeObjectURL(removed.previewUrl);
        previewUrls.current.delete(removed.previewUrl);
      }
      return current.filter((image) => image.id !== id);
    });
    setError(undefined);
  };

  const clear = () => {
    for (const previewUrl of previewUrls.current) {
      URL.revokeObjectURL(previewUrl);
    }
    previewUrls.current.clear();
    setImages([]);
    setError(undefined);
  };

  return { addFiles, clear, error, handleRemove: remove, images } as const;
};
