"use client";

import type { CommentEntityType } from "@capakraken/shared";
import { createPortal } from "react-dom";
import { useCallback, useEffect, useRef, useState } from "react";
import { trpc } from "~/lib/trpc/client.js";
import { useAnchoredOverlay } from "~/hooks/useAnchoredOverlay.js";

interface CommentInputProps {
  entityType: CommentEntityType;
  entityId: string;
  parentId?: string;
  onSubmit: (body: string) => void;
  onCancel?: () => void;
  isSubmitting?: boolean;
  placeholder?: string;
  autoFocus?: boolean;
}

interface MentionCandidate {
  id: string;
  name: string | null;
  email: string;
}

export function CommentInput({
  entityType,
  entityId,
  parentId: _parentId,
  onSubmit,
  onCancel,
  isSubmitting = false,
  placeholder = "Write a comment... Use @ to mention someone",
  autoFocus = false,
}: CommentInputProps) {
  const [body, setBody] = useState("");
  const [mentionQuery, setMentionQuery] = useState<string | null>(null);
  const [mentionIndex, setMentionIndex] = useState(0);
  const [cursorPosition, setCursorPosition] = useState(0);
  const textareaRef = useRef<HTMLTextAreaElement>(null);

  const usersQuery = trpc.comment.listMentionCandidates.useQuery({
    entityType,
    entityId,
    ...(mentionQuery && mentionQuery.length > 0 ? { query: mentionQuery } : {}),
  }, {
    enabled: mentionQuery !== null,
    staleTime: 60_000,
  });

  const filteredUsers: MentionCandidate[] =
    mentionQuery !== null ? (usersQuery.data ?? []).slice(0, 8) : [];
  const mentionOpen = mentionQuery !== null && filteredUsers.length > 0;
  const { panelRef, position } = useAnchoredOverlay<HTMLTextAreaElement>({
    open: mentionOpen,
    onClose: () => setMentionQuery(null),
    align: "start",
    triggerRef: textareaRef,
  });

  // Reset mention index when filtered list changes
  useEffect(() => {
    setMentionIndex(0);
  }, [mentionQuery]);

  const handleChange = useCallback(
    (e: React.ChangeEvent<HTMLTextAreaElement>) => {
      const value = e.target.value;
      const cursor = e.target.selectionStart ?? value.length;
      setBody(value);
      setCursorPosition(cursor);

      // Detect if we are in a @mention context
      const textBeforeCursor = value.slice(0, cursor);
      const atMatch = textBeforeCursor.match(/@([^\s@]*)$/);

      if (atMatch) {
        setMentionQuery(atMatch[1]!);
      } else {
        setMentionQuery(null);
      }
    },
    [],
  );

  const insertMention = useCallback(
    (user: MentionCandidate) => {
      const textBeforeCursor = body.slice(0, cursorPosition);
      const textAfterCursor = body.slice(cursorPosition);

      // Find the @ that triggered this mention
      const atMatch = textBeforeCursor.match(/@([^\s@]*)$/);
      if (!atMatch) return;

      const atStart = textBeforeCursor.length - atMatch[0].length;
      const displayName = user.name ?? user.email;
      const mentionText = `@[${displayName}](${user.id}) `;

      const newBody =
        textBeforeCursor.slice(0, atStart) + mentionText + textAfterCursor;
      setBody(newBody);
      setMentionQuery(null);

      // Focus and set cursor position
      const newCursorPos = atStart + mentionText.length;
      requestAnimationFrame(() => {
        const ta = textareaRef.current;
        if (ta) {
          ta.focus();
          ta.selectionStart = newCursorPos;
          ta.selectionEnd = newCursorPos;
        }
      });
    },
    [body, cursorPosition],
  );

  const handleKeyDown = useCallback(
    (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
      // Handle mention dropdown navigation
      if (mentionQuery !== null && filteredUsers.length > 0) {
        if (e.key === "ArrowDown") {
          e.preventDefault();
          setMentionIndex((prev) =>
            prev < filteredUsers.length - 1 ? prev + 1 : 0,
          );
          return;
        }
        if (e.key === "ArrowUp") {
          e.preventDefault();
          setMentionIndex((prev) =>
            prev > 0 ? prev - 1 : filteredUsers.length - 1,
          );
          return;
        }
        if (e.key === "Enter" || e.key === "Tab") {
          e.preventDefault();
          insertMention(filteredUsers[mentionIndex]!);
          return;
        }
        if (e.key === "Escape") {
          e.preventDefault();
          setMentionQuery(null);
          return;
        }
      }

      // Submit on Ctrl+Enter / Cmd+Enter
      if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) {
        e.preventDefault();
        if (body.trim().length > 0 && !isSubmitting) {
          onSubmit(body.trim());
          setBody("");
        }
      }
    },
    [mentionQuery, filteredUsers, mentionIndex, insertMention, body, isSubmitting, onSubmit],
  );

  function handleSubmitClick() {
    if (body.trim().length > 0 && !isSubmitting) {
      onSubmit(body.trim());
      setBody("");
    }
  }

  return (
    <div className="relative">
      <textarea
        ref={textareaRef}
        value={body}
        onChange={handleChange}
        onKeyDown={handleKeyDown}
        placeholder={placeholder}
        autoFocus={autoFocus}
        disabled={isSubmitting}
        rows={3}
        className="w-full rounded-xl border border-gray-200 dark:border-gray-600 bg-white dark:bg-gray-800 px-4 py-3 text-sm text-gray-900 dark:text-gray-100 placeholder:text-gray-400 focus:border-brand-400 dark:focus:border-sky-500 focus:outline-none focus:ring-2 focus:ring-brand-100 dark:focus:ring-sky-900 disabled:opacity-60 resize-y"
      />

      {/* Mention autocomplete dropdown */}
      {mentionOpen && typeof document !== "undefined"
        ? createPortal(
            <div
              ref={panelRef}
              className="fixed z-[9998] w-72 overflow-hidden rounded-xl border border-gray-200 bg-white shadow-lg dark:border-gray-600 dark:bg-gray-800"
              style={{
                top: position.top,
                left: position.left,
              }}
            >
              {filteredUsers.map((user, idx) => (
                <button
                  key={user.id}
                  type="button"
                  onMouseDown={(e) => {
                    e.preventDefault();
                    insertMention(user);
                  }}
                  className={`flex w-full items-center gap-3 px-3 py-2 text-left text-sm transition-colors ${
                    idx === mentionIndex
                      ? "bg-brand-50 dark:bg-sky-900/40 text-brand-700 dark:text-sky-200"
                      : "text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700"
                  }`}
                >
                  <span className="flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-brand-100 text-xs font-semibold text-brand-700 dark:bg-sky-800 dark:text-sky-200">
                    {(user.name ?? user.email).charAt(0).toUpperCase()}
                  </span>
                  <span className="truncate">
                    <span className="font-medium">{user.name ?? "—"}</span>
                    <span className="ml-1 text-xs text-gray-400">{user.email}</span>
                  </span>
                </button>
              ))}
            </div>,
            document.body,
          )
        : null}

      <div className="mt-2 flex items-center justify-between">
        <span className="text-xs text-gray-400">
          Ctrl+Enter to submit
        </span>
        <div className="flex gap-2">
          {onCancel && (
            <button
              type="button"
              onClick={onCancel}
              disabled={isSubmitting}
              className="rounded-lg px-3 py-1.5 text-xs font-medium text-gray-500 dark:text-gray-400 transition-colors hover:bg-gray-100 dark:hover:bg-gray-700 disabled:opacity-60"
            >
              Cancel
            </button>
          )}
          <button
            type="button"
            onClick={handleSubmitClick}
            disabled={body.trim().length === 0 || isSubmitting}
            className="rounded-lg bg-brand-600 dark:bg-sky-600 px-3 py-1.5 text-xs font-semibold text-white transition-colors hover:bg-brand-700 dark:hover:bg-sky-700 disabled:opacity-40 disabled:cursor-not-allowed"
          >
            {isSubmitting ? "Sending..." : "Comment"}
          </button>
        </div>
      </div>
    </div>
  );
}
