import { useRef, useState } from "react";
import type { ChangeEvent, DragEvent as ReactDragEvent } from "react";
import type { ChatAttachment } from "@qjclaw/shared-types";
import {
  IMAGE_ATTACHMENT_EXTENSIONS,
  SUPPORTED_ATTACHMENT_EXTENSIONS
} from "../../lib/constants";
import { desktopApi } from "../../lib/desktop-api";

interface UseComposerAttachmentsOptions {
  setErrorText: (value: string) => void;
}

export function useComposerAttachments({ setErrorText }: UseComposerAttachmentsOptions) {
  const [composerAttachments, setComposerAttachments] = useState<ChatAttachment[]>([]);
  const [isComposerDragOver, setIsComposerDragOver] = useState(false);
  const attachmentInputRef = useRef<HTMLInputElement | null>(null);
  const composerDragDepthRef = useRef(0);

  function resolveComposerAttachmentKind(file: File, localPath: string): ChatAttachment["kind"] | null {
    if (file.type.startsWith("image/")) {
      return "image";
    }

    const extension = (file.name ? file.name.slice(file.name.lastIndexOf(".")) : localPath.slice(localPath.lastIndexOf("."))).toLowerCase();
    if (IMAGE_ATTACHMENT_EXTENSIONS.has(extension)) {
      return "image";
    }
    if (SUPPORTED_ATTACHMENT_EXTENSIONS.has(extension)) {
      return "file";
    }
    return null;
  }

  function appendComposerAttachments(nextAttachments: ChatAttachment[]) {
    setComposerAttachments((current) => {
      const merged = [...current];
      const seen = new Set(current.map((attachment) => attachment.localPath.toLowerCase()));
      for (const attachment of nextAttachments) {
        const key = attachment.localPath.toLowerCase();
        if (seen.has(key)) {
          continue;
        }
        seen.add(key);
        merged.push(attachment);
      }
      return merged;
    });
  }

  function clearComposerAttachment() {
    setErrorText("");
    setComposerAttachments([]);
    if (attachmentInputRef.current) {
      attachmentInputRef.current.value = "";
    }
  }

  function removeComposerAttachment(localPath: string) {
    setComposerAttachments((current) => current.filter((attachment) => attachment.localPath !== localPath));
  }

  function acceptComposerAttachmentFile(file: File) {
    const localPath = (file as File & { path?: string }).path?.trim();
    if (!localPath) {
      setErrorText("The desktop client did not provide a local file path, so this attachment cannot be sent into the project workspace.");
      return;
    }

    const kind = resolveComposerAttachmentKind(file, localPath);
    if (!kind) {
      setErrorText("Supported attachments: images, MP3, PDF, PPT, Excel, Word, CSV, TXT, Markdown, and JSON.");
      return;
    }

    setErrorText("");
    appendComposerAttachments([{
      kind,
      name: file.name || localPath.split(/[\\/]/).pop() || "attachment",
      mimeType: file.type || "application/octet-stream",
      localPath
    }]);
  }

  function handleComposerDragEnter(event: ReactDragEvent<HTMLFormElement>) {
    if (!event.dataTransfer?.files?.length) {
      return;
    }

    event.preventDefault();
    composerDragDepthRef.current += 1;
    setIsComposerDragOver(true);
  }

  function handleComposerDragOver(event: ReactDragEvent<HTMLFormElement>) {
    if (!event.dataTransfer?.files?.length) {
      return;
    }

    event.preventDefault();
    event.dataTransfer.dropEffect = "copy";
  }

  function handleComposerDragLeave(event: ReactDragEvent<HTMLFormElement>) {
    if (!event.dataTransfer?.files?.length) {
      return;
    }

    event.preventDefault();
    composerDragDepthRef.current = Math.max(0, composerDragDepthRef.current - 1);
    if (composerDragDepthRef.current === 0) {
      setIsComposerDragOver(false);
    }
  }

  function handleComposerDrop(event: ReactDragEvent<HTMLFormElement>) {
    if (!event.dataTransfer?.files?.length) {
      return;
    }

    event.preventDefault();
    composerDragDepthRef.current = 0;
    setIsComposerDragOver(false);
    const files = Array.from(event.dataTransfer.files);
    for (const file of files) {
      acceptComposerAttachmentFile(file);
    }
  }

  async function openAttachmentPicker() {
    if (window.qjcDesktop) {
      const attachments = await desktopApi.chat.pickAttachments();
      if (!attachments.length) {
        return;
      }
      setErrorText("");
      appendComposerAttachments(attachments);
      return;
    }

    attachmentInputRef.current?.click();
  }

  function handleAttachmentSelection(event: ChangeEvent<HTMLInputElement>) {
    const files = event.target.files ? Array.from(event.target.files) : [];
    if (!files.length) {
      return;
    }

    for (const file of files) {
      acceptComposerAttachmentFile(file);
    }
    event.target.value = "";
  }

  return {
    attachmentInputRef,
    composerAttachments,
    isComposerDragOver,
    clearComposerAttachment,
    removeComposerAttachment,
    openAttachmentPicker,
    handleAttachmentSelection,
    handleComposerDragEnter,
    handleComposerDragOver,
    handleComposerDragLeave,
    handleComposerDrop
  };
}
