import React, { useState, useRef, useEffect, useCallback, type KeyboardEvent } from 'react';
import { FaSpinner, FaUser } from 'react-icons/fa';
import type { MentionUser } from '../services/commentService';
import API_CONFIG from '../config/api';

// ============================================================
// MentionInput – a textarea that shows a dropdown when user
// types '@' and lets them pick a user to @mention.
//
// The final output is an HTML string with Frappe-style mention
// markup so ERPNext recognises it exactly like its own editor.
// ============================================================

interface MentionInputProps {
  value: string;                          // plain-text draft
  onChange: (text: string) => void;
  onSubmit: (html: string) => void;       // returns formatted HTML
  placeholder?: string;
  disabled?: boolean;
  mentionUsers: MentionUser[];
  mentionLoading: boolean;
  onMentionSearch: (query: string) => void;
  posting?: boolean;
}

/** Stores an inserted mention so we can convert to HTML later */
interface InsertedMention {
  startIndex: number;
  displayText: string;
  userId: string;     // email
  fullName: string;
}

const MentionInput: React.FC<MentionInputProps> = ({
  value,
  onChange,
  onSubmit,
  placeholder = 'Type a comment… Use @ to mention someone',
  disabled = false,
  mentionUsers,
  mentionLoading,
  onMentionSearch,
  posting = false,
}) => {
  const textareaRef = useRef<HTMLTextAreaElement>(null);
  const dropdownRef = useRef<HTMLDivElement>(null);

  // Mention trigger state
  const [showMentionDropdown, setShowMentionDropdown] = useState(false);
  const [mentionQuery, setMentionQuery] = useState('');
  const [mentionStartPos, setMentionStartPos] = useState<number | null>(null);
  const [selectedIndex, setSelectedIndex] = useState(0);
  const [insertedMentions, setInsertedMentions] = useState<InsertedMention[]>([]);

  // Dropdown position
  const [dropdownPos, setDropdownPos] = useState({ top: 0, left: 0 });

  // ── Calculate dropdown position relative to textarea ────
  const updateDropdownPosition = useCallback(() => {
    const ta = textareaRef.current;
    if (!ta) return;
    // Place the dropdown above the textarea bottom
    const rect = ta.getBoundingClientRect();
    const parentRect = ta.offsetParent?.getBoundingClientRect() ?? rect;
    setDropdownPos({
      top: ta.offsetTop - 4,   // above textarea
      left: ta.offsetLeft,
    });
  }, []);

  // ── Handle text changes ─────────────────────────────────
  const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
    const newValue = e.target.value;
    const cursorPos = e.target.selectionStart ?? 0;
    onChange(newValue);

    // Check for active mention trigger
    const textBeforeCursor = newValue.substring(0, cursorPos);
    const lastAtIndex = textBeforeCursor.lastIndexOf('@');

    if (lastAtIndex !== -1) {
      // Check that @ is at start or preceded by a space/newline
      const charBefore = lastAtIndex > 0 ? newValue[lastAtIndex - 1] : ' ';
      if (charBefore === ' ' || charBefore === '\n' || lastAtIndex === 0) {
        const query = textBeforeCursor.substring(lastAtIndex + 1);
        // Only activate if query doesn't contain spaces (single-word search)
        if (!query.includes(' ') || query.length <= 30) {
          setShowMentionDropdown(true);
          setMentionQuery(query);
          setMentionStartPos(lastAtIndex);
          setSelectedIndex(0);
          onMentionSearch(query);
          updateDropdownPosition();
          return;
        }
      }
    }

    // No active mention
    setShowMentionDropdown(false);
    setMentionStartPos(null);
  };

  // ── Insert a mention into the text ──────────────────────
  const insertMention = useCallback(
    (user: MentionUser) => {
      if (mentionStartPos === null) return;

      const ta = textareaRef.current;
      const before = value.substring(0, mentionStartPos);
      const cursorPos = ta?.selectionStart ?? mentionStartPos + mentionQuery.length + 1;
      const after = value.substring(cursorPos);

      const displayText = user.full_name || user.name;
      const newText = `${before}@${displayText} ${after}`;

      // Track the mention
      setInsertedMentions((prev) => [
        ...prev,
        {
          startIndex: mentionStartPos,
          displayText,
          userId: user.name,
          fullName: user.full_name || user.name,
        },
      ]);

      onChange(newText);
      setShowMentionDropdown(false);
      setMentionStartPos(null);
      setMentionQuery('');

      // Refocus and place cursor after mention
      setTimeout(() => {
        if (ta) {
          ta.focus();
          const newPos = before.length + displayText.length + 2; // +2 for @ and space
          ta.selectionStart = newPos;
          ta.selectionEnd = newPos;
        }
      }, 0);
    },
    [mentionStartPos, mentionQuery, value, onChange]
  );

  // ── Keyboard navigation inside dropdown ─────────────────
  const handleKeyDown = (e: KeyboardEvent<HTMLTextAreaElement>) => {
    if (showMentionDropdown && mentionUsers.length > 0) {
      switch (e.key) {
        case 'ArrowDown':
          e.preventDefault();
          setSelectedIndex((prev) => Math.min(prev + 1, mentionUsers.length - 1));
          return;
        case 'ArrowUp':
          e.preventDefault();
          setSelectedIndex((prev) => Math.max(prev - 1, 0));
          return;
        case 'Enter':
          e.preventDefault();
          insertMention(mentionUsers[selectedIndex]);
          return;
        case 'Escape':
          e.preventDefault();
          setShowMentionDropdown(false);
          return;
      }
    }

    // Ctrl/Cmd + Enter to submit
    if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) {
      e.preventDefault();
      handleSubmit();
    }
  };

  // ── Build Frappe-compatible HTML from plain text + mentions ─
  const buildHtml = useCallback(
    (text: string): string => {
      let html = text;
      const baseUrl = API_CONFIG.BASE_URL || window.location.origin;

      // Replace each tracked @mention with the Frappe mention markup
      // Process in reverse order of startIndex so positions don't shift
      const sorted = [...insertedMentions].sort((a, b) => b.startIndex - a.startIndex);

      for (const m of sorted) {
        const mentionText = `@${m.displayText}`;
        const idx = html.indexOf(mentionText);
        if (idx === -1) continue;

        const profileUrl = `${baseUrl}/app/user-profile/${encodeURIComponent(m.userId)}`;
        const mentionHtml =
          `<span class="mention" ` +
          `data-id="${m.userId}" ` +
          `data-value="&lt;a href=&quot;${profileUrl}&quot; target=&quot;_blank&quot;&gt;${m.fullName}" ` +
          `data-denotation-char="@" ` +
          `data-is-group="false" ` +
          `data-link="${profileUrl}">` +
          `\uFEFF<span contenteditable="false">` +
          `<span class="ql-mention-denotation-char">@</span>` +
          `<a href="${profileUrl}" target="_blank">${m.fullName}</a>` +
          `</span>\uFEFF</span>`;

        html = html.substring(0, idx) + mentionHtml + html.substring(idx + mentionText.length);
      }

      // Escape remaining HTML chars (basic), then wrap newlines
      // We do NOT escape the mention markup we just inserted
      // Instead, split by mention spans, escape non-mention parts, and rejoin
      // Simple approach: since mentions are already HTML, just convert newlines to <br>
      html = html.replace(/\n/g, '<br>');

      return `<div class="ql-editor read-mode"><p>${html}</p></div>`;
    },
    [insertedMentions]
  );

  // ── Submit handler ──────────────────────────────────────
  const handleSubmit = () => {
    const trimmed = value.trim();
    if (!trimmed || posting) return;

    const html = buildHtml(trimmed);
    onSubmit(html);
    setInsertedMentions([]);
  };

  // ── Close dropdown on outside click ─────────────────────
  useEffect(() => {
    const handleClickOutside = (e: MouseEvent) => {
      if (
        dropdownRef.current &&
        !dropdownRef.current.contains(e.target as Node) &&
        textareaRef.current &&
        !textareaRef.current.contains(e.target as Node)
      ) {
        setShowMentionDropdown(false);
      }
    };
    document.addEventListener('mousedown', handleClickOutside);
    return () => document.removeEventListener('mousedown', handleClickOutside);
  }, []);

  // ── Scroll selected item into view ──────────────────────
  useEffect(() => {
    if (!dropdownRef.current) return;
    const item = dropdownRef.current.querySelector(`[data-idx="${selectedIndex}"]`);
    item?.scrollIntoView({ block: 'nearest' });
  }, [selectedIndex]);

  const baseUrl = API_CONFIG.BASE_URL || '';

  return (
    <div className="relative">
      {/* ── Mention dropdown ──────────────────────────────── */}
      {showMentionDropdown && (
        <div
          ref={dropdownRef}
          className="absolute z-50 bottom-full mb-1 w-72 max-h-52 overflow-y-auto
                     bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-600
                     rounded-lg shadow-lg"
          style={{ left: 0 }}
        >
          {mentionLoading && mentionUsers.length === 0 ? (
            <div className="flex items-center gap-2 px-3 py-4 text-sm text-gray-500 dark:text-gray-400">
              <FaSpinner className="animate-spin" size={12} />
              Searching users…
            </div>
          ) : mentionUsers.length === 0 ? (
            <div className="px-3 py-4 text-sm text-gray-500 dark:text-gray-400">
              No users found
            </div>
          ) : (
            mentionUsers.map((user, idx) => (
              <button
                key={user.name}
                data-idx={idx}
                type="button"
                className={`w-full flex items-center gap-2.5 px-3 py-2 text-left transition-colors
                  ${idx === selectedIndex
                    ? 'bg-teal-50 dark:bg-teal-900/30 text-teal-800 dark:text-teal-200'
                    : 'text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700'
                  }`}
                onMouseEnter={() => setSelectedIndex(idx)}
                onMouseDown={(e) => {
                  e.preventDefault(); // keep focus on textarea
                  insertMention(user);
                }}
              >
                {/* Avatar */}
                {user.user_image ? (
                  <img
                    src={`${baseUrl}${user.user_image}`}
                    alt=""
                    className="w-7 h-7 rounded-full object-cover flex-shrink-0"
                  />
                ) : (
                  <div className="w-7 h-7 rounded-full bg-gray-200 dark:bg-gray-600 flex items-center justify-center flex-shrink-0">
                    <FaUser className="text-gray-500 dark:text-gray-400" size={10} />
                  </div>
                )}
                <div className="min-w-0 flex-1">
                  <p className="text-sm font-medium truncate">
                    {user.full_name || user.name}
                  </p>
                  <p className="text-xs text-gray-500 dark:text-gray-400 truncate">
                    {user.name}
                  </p>
                </div>
              </button>
            ))
          )}
        </div>
      )}

      {/* ── Textarea + submit ──────────────────────────────── */}
      <div className="flex gap-2 items-end">
        <textarea
          ref={textareaRef}
          value={value}
          onChange={handleChange}
          onKeyDown={handleKeyDown}
          placeholder={placeholder}
          disabled={disabled || posting}
          rows={3}
          className="flex-1 px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg
                     bg-white dark:bg-gray-700 text-gray-900 dark:text-white text-sm
                     disabled:bg-gray-100 dark:disabled:bg-gray-800
                     focus:outline-none focus:ring-2 focus:ring-teal-500 resize-none
                     placeholder:text-gray-400 dark:placeholder:text-gray-500"
        />
        <button
          type="button"
          onClick={handleSubmit}
          disabled={disabled || posting || !value.trim()}
          className="px-4 py-2 bg-teal-600 hover:bg-teal-700 disabled:bg-teal-600/50
                     text-white text-sm font-medium rounded-lg transition-colors
                     disabled:cursor-not-allowed flex items-center gap-1.5 h-10 flex-shrink-0"
        >
          {posting ? (
            <>
              <FaSpinner className="animate-spin" size={12} />
              <span>Posting…</span>
            </>
          ) : (
            <span>Comment</span>
          )}
        </button>
      </div>

      {/* Hint */}
      <p className="mt-1 text-[10px] text-gray-400 dark:text-gray-500">
        <kbd className="px-1 py-0.5 bg-gray-100 dark:bg-gray-700 rounded text-[9px]">@</kbd> to mention
        &nbsp;·&nbsp;
        <kbd className="px-1 py-0.5 bg-gray-100 dark:bg-gray-700 rounded text-[9px]">Ctrl+Enter</kbd> to post
      </p>
    </div>
  );
};

export default MentionInput;