import { useEffect, useRef, useState } from "react";
import { Send, Loader2, Paperclip, X } from "lucide-react";
import { Button } from "@/components/ui/button";
import { ChatSlashCommandPopover } from "./ChatSlashCommandPopover";
import { ChatMentionPopover } from "./ChatMentionPopover";
import { ChatFileDropZone } from "./ChatFileDropZone";
import { cn } from "../lib/utils";
import type { Agent } from "@paperclipai/shared";
import type { PendingFile } from "../hooks/useChatFileUpload";

interface ChatInputProps {
  onSend: (content: string) => void;
  isSubmitting?: boolean;
  disabled?: boolean;
  placeholder?: string;
  // Popover support
  agents?: Agent[];
  agentsLoading?: boolean;
  // File upload support
  onFilesPicked?: (files: File[]) => void;
  pendingFiles?: PendingFile[];
  onRemoveFile?: (id: string) => void;
}

export function ChatInput({
  onSend,
  isSubmitting = false,
  disabled = false,
  placeholder = "Message your agent...",
  agents = [],
  agentsLoading = false,
  onFilesPicked,
  pendingFiles,
  onRemoveFile,
}: ChatInputProps) {
  const [value, setValue] = useState("");
  const textareaRef = useRef<HTMLTextAreaElement>(null);

  // Slash command popover state
  const [slashOpen, setSlashOpen] = useState(false);
  const [slashQuery, setSlashQuery] = useState("");

  // @mention popover state
  const [mentionOpen, setMentionOpen] = useState(false);
  const [mentionQuery, setMentionQuery] = useState("");

  // Auto-resize fallback for browsers without field-sizing: content support
  useEffect(() => {
    const el = textareaRef.current;
    if (!el) return;
    el.style.height = "auto";
    el.style.height = `${el.scrollHeight}px`;
  }, [value]);

  function submit() {
    const trimmed = value.trim();
    if (!trimmed || isSubmitting || disabled) return;
    onSend(trimmed);
    setValue("");
    setSlashOpen(false);
    setMentionOpen(false);
    if (textareaRef.current) {
      textareaRef.current.style.height = "auto";
    }
  }

  function handleChange(e: React.ChangeEvent<HTMLTextAreaElement>) {
    const val = e.target.value;
    setValue(val);

    // Slash command: opens when / is the first character
    if (val.startsWith("/")) {
      setSlashOpen(true);
      setSlashQuery(val);
    } else {
      setSlashOpen(false);
    }

    // @mention: opens when @ appears with a word boundary before it
    const mentionMatch = val.match(/@(\w*)$/);
    if (mentionMatch) {
      setMentionOpen(true);
      setMentionQuery(mentionMatch[1] ?? "");
    } else {
      setMentionOpen(false);
    }
  }

  function handleSlashSelect(command: string) {
    setValue(command + " ");
    setSlashOpen(false);
    textareaRef.current?.focus();
  }

  function handleMentionSelect(agentName: string) {
    // Replace the @query with @agentName
    const val = value.replace(/@\w*$/, `@${agentName} `);
    setValue(val);
    setMentionOpen(false);
    textareaRef.current?.focus();
  }

  function handleKeyDown(e: React.KeyboardEvent<HTMLTextAreaElement>) {
    if (e.key === "Escape") {
      if (slashOpen) {
        setSlashOpen(false);
        return;
      }
      if (mentionOpen) {
        setMentionOpen(false);
        return;
      }
      e.preventDefault();
      setValue("");
      if (textareaRef.current) {
        textareaRef.current.style.height = "auto";
      }
      return;
    }
    if (e.key === "Enter" && !e.shiftKey && !e.nativeEvent.isComposing) {
      e.preventDefault();
      submit();
    }
    // Shift+Enter falls through to default behavior (inserts newline)
  }

  function handlePaste(e: React.ClipboardEvent) {
    const files = Array.from(e.clipboardData.files);
    if (files.length > 0) {
      e.preventDefault();
      onFilesPicked?.(files);
    }
    // If no files, allow default paste behavior (text)
  }

  const isEmpty = value.trim().length === 0;

  const textarea = (
    <textarea
      ref={textareaRef}
      value={value}
      onChange={handleChange}
      onKeyDown={handleKeyDown}
      onPaste={handlePaste}
      placeholder={placeholder}
      rows={1}
      disabled={disabled}
      className={cn(
        "flex w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm",
        "placeholder:text-muted-foreground",
        "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
        "disabled:cursor-not-allowed disabled:opacity-50",
        "resize-none min-h-[40px] max-h-[160px] overflow-y-auto",
        // field-sizing: content for modern browsers (Chrome 123+, Firefox 129+)
        "[field-sizing:content]",
      )}
    />
  );

  return (
    <ChatFileDropZone
      onFilesDropped={(files) => files.forEach((f) => onFilesPicked?.([f]))}
      disabled={disabled}
    >
      <form
        onSubmit={(e) => {
          e.preventDefault();
          submit();
        }}
        className="flex items-end gap-2"
      >
        {/* Slash command takes priority over mention popover */}
        <div className="flex-1 relative">
          {/* Pending file chips above textarea */}
          {pendingFiles && pendingFiles.length > 0 && (
            <div className="flex flex-wrap gap-1 px-1 pb-1">
              {pendingFiles.map((pf) => (
                <div key={pf.id} className="flex items-center gap-1 rounded bg-muted px-2 py-1 text-xs">
                  {pf.status === "uploading" && (
                    <Loader2 className="h-3 w-3 animate-spin" />
                  )}
                  <span className="max-w-[120px] truncate">{pf.name}</span>
                  {pf.status === "uploading" && (
                    <span className="text-muted-foreground">{pf.progress}%</span>
                  )}
                  <button
                    type="button"
                    className="ml-1 text-muted-foreground hover:text-foreground"
                    onClick={() => onRemoveFile?.(pf.id)}
                  >
                    <X className="h-3 w-3" />
                  </button>
                </div>
              ))}
            </div>
          )}

          <ChatSlashCommandPopover
            open={slashOpen && !mentionOpen}
            onOpenChange={setSlashOpen}
            onSelect={handleSlashSelect}
            query={slashQuery}
          >
            <ChatMentionPopover
              open={mentionOpen && !slashOpen}
              onOpenChange={setMentionOpen}
              onSelect={handleMentionSelect}
              query={mentionQuery}
              agents={agents}
              isLoading={agentsLoading}
            >
              {textarea}
            </ChatMentionPopover>
          </ChatSlashCommandPopover>
        </div>

        {/* File attach button */}
        <label className="shrink-0 cursor-pointer">
          <input
            type="file"
            multiple
            className="hidden"
            onChange={(e) => {
              const files = Array.from(e.target.files ?? []);
              if (files.length > 0) onFilesPicked?.(files);
              e.target.value = ""; // reset for re-selection
            }}
            disabled={disabled}
          />
          <Button type="button" variant="ghost" size="icon" asChild disabled={disabled}>
            <span><Paperclip className="h-4 w-4" /></span>
          </Button>
        </label>

        <Button
          type="submit"
          variant="ghost"
          size="icon"
          disabled={isEmpty || isSubmitting || disabled}
          aria-label="Send message"
          className="shrink-0"
        >
          {isSubmitting ? (
            <Loader2 className="h-4 w-4 animate-spin" />
          ) : (
            <Send className="h-4 w-4" />
          )}
        </Button>
      </form>
    </ChatFileDropZone>
  );
}
