import React, { useEffect, useRef, useState } from 'react';
import { MoreHorizontal, Pencil, Trash2 } from 'lucide-react';
import { Conversation, useRenameConversation } from '../../contexts/ChatContext';
import useRenderTracker from '../../hooks/useRenderTracker';
import { cn } from '../../utils/classNames';

interface ConversationGroupProps {
  category: string;
  conversations: Conversation[];
  currentConversationId: string | null;
  onSelectConversation: (id: string) => void;
  onDeleteConversation: (conversationName: string, conversationId: string) => void;
  className?: string;
}

const AnimatedConversationTitle = ({ title }: { title: string }) => {
  const [displayTitle, setDisplayTitle] = useState(title);
  const previousTitleRef = useRef(title);

  useEffect(() => {
    if (previousTitleRef.current === title) return;

    previousTitleRef.current = title;
    if (!title) {
      setDisplayTitle('');
      return;
    }

    let index = 0;
    setDisplayTitle('');
    const timerId = window.setInterval(() => {
      index += 1;
      setDisplayTitle(title.slice(0, index));
      if (index >= title.length) {
        window.clearInterval(timerId);
      }
    }, 24);

    return () => window.clearInterval(timerId);
  }, [title]);

  return <>{displayTitle}</>;
};

const ConversationGroup: React.FC<ConversationGroupProps> = ({
  category,
  conversations,
  currentConversationId,
  onSelectConversation,
  onDeleteConversation,
  className,
}) => {
  const renameConversation = useRenameConversation();
  const [menuId, setMenuId] = useState<string | null>(null);
  const [editingId, setEditingId] = useState<string | null>(null);
  const [draft, setDraft] = useState('');
  const menuRef = useRef<HTMLDivElement>(null);

  // Close the options menu on any click outside it, or on Escape. (A `fixed`
  // overlay can't be relied on here — an ancestor transform would scope it to
  // the sidebar instead of the viewport.)
  useEffect(() => {
    if (!menuId) return;
    const handlePointerDown = (event: PointerEvent) => {
      const menu = menuRef.current;
      if (!menu) return;
      // The app mounts in a Shadow DOM, so a document-level event's `target` is
      // retargeted to the shadow host. Use composedPath() to see the real path
      // through the shadow boundary and detect clicks inside the menu.
      const path = event.composedPath();
      if (path.length ? !path.includes(menu) : !menu.contains(event.target as Node)) {
        setMenuId(null);
      }
    };
    const handleKeyDown = (event: KeyboardEvent) => {
      if (event.key === 'Escape') setMenuId(null);
    };
    document.addEventListener('pointerdown', handlePointerDown);
    document.addEventListener('keydown', handleKeyDown);
    return () => {
      document.removeEventListener('pointerdown', handlePointerDown);
      document.removeEventListener('keydown', handleKeyDown);
    };
  }, [menuId]);

  useRenderTracker('ConversationGroup', {
    category,
    conversations,
    currentConversationId,
    onSelectConversation,
    onDeleteConversation,
  });

  const startRename = (conv: Conversation) => {
    setMenuId(null);
    setDraft(conv.title || 'New Chat');
    setEditingId(conv.conversation_id);
  };

  const commitRename = (conv: Conversation) => {
    const trimmed = draft.trim().replace(/\s+/g, ' ');
    // Only send the rename if the name actually changed — clicking off an
    // untouched field shouldn't fire a request. Baseline matches what
    // startRename seeds, normalized the same way.
    const original = (conv.title || 'New Chat').trim().replace(/\s+/g, ' ');
    if (trimmed && trimmed !== original) void renameConversation(conv.conversation_id, trimmed);
    setEditingId(null);
  };

  return (
    <div className={cn('px-2', className)}>
      <div className="sticky top-0 z-10 bg-app-surface px-2 pb-2 pt-1 text-xs font-semibold uppercase tracking-wide text-app-muted-strong">
        {category}
      </div>
      <div className="space-y-0.5">
        {conversations
          .sort((a, b) => b.updated_at - a.updated_at)
          .map((conv) => {
            const isActive = conv.conversation_id === currentConversationId;
            const title = conv.title || 'New Chat';

            if (editingId === conv.conversation_id) {
              return (
                <input
                  key={conv.conversation_id}
                  autoFocus
                  value={draft}
                  onChange={(e) => setDraft(e.target.value)}
                  onBlur={() => commitRename(conv)}
                  onKeyDown={(e) => {
                    if (e.key === 'Enter') commitRename(conv);
                    else if (e.key === 'Escape') setEditingId(null);
                  }}
                  aria-label="Rename conversation"
                  className="block w-full rounded-md border border-brand bg-app-surface px-2 py-2 text-sm text-app-text outline-none ring-2 ring-brand/25"
                />
              );
            }

            const menuOpen = menuId === conv.conversation_id;
            return (
              <div key={conv.conversation_id} className="group relative">
                <button
                  type="button"
                  onClick={() => onSelectConversation(conv.conversation_id)}
                  title={title}
                  aria-current={isActive ? 'true' : undefined}
                  className={cn(
                    'block w-full truncate rounded-md px-2 py-2 text-left text-sm transition-[padding,background-color,color] group-hover:pr-9 focus:outline-none focus-visible:ring-2 focus-visible:ring-brand',
                    menuOpen && 'pr-9',
                    isActive
                      ? 'bg-app-selected font-medium text-app-text'
                      : 'text-app-muted hover:bg-app-surface-hover hover:text-app-text',
                  )}
                >
                  <AnimatedConversationTitle title={title} />
                </button>

                <button
                  type="button"
                  onClick={() => setMenuId(menuOpen ? null : conv.conversation_id)}
                  aria-label={`Conversation options: ${title}`}
                  aria-haspopup="menu"
                  aria-expanded={menuOpen}
                  className={cn(
                    'absolute right-1 top-1/2 flex h-7 w-7 -translate-y-1/2 items-center justify-center rounded-md text-app-muted transition-opacity hover:bg-app-surface-hover hover:text-app-text focus:outline-none focus-visible:opacity-100 focus-visible:ring-2 focus-visible:ring-brand group-hover:opacity-100',
                    menuOpen ? 'opacity-100' : 'opacity-0',
                  )}
                >
                  <MoreHorizontal size={16} />
                </button>

                {menuOpen && (
                    <div
                      ref={menuRef}
                      role="menu"
                      className="absolute right-1 top-9 z-50 w-36 overflow-hidden rounded-lg border border-app-border bg-app-elevated p-1 shadow-card"
                    >
                      <button
                        type="button"
                        role="menuitem"
                        onClick={() => startRename(conv)}
                        className="flex w-full items-center gap-2 rounded-md px-2.5 py-1.5 text-sm text-app-text transition-colors hover:bg-app-surface-hover"
                      >
                        <Pencil size={14} className="text-app-muted" />
                        Rename
                      </button>
                      <button
                        type="button"
                        role="menuitem"
                        onClick={() => {
                          setMenuId(null);
                          onDeleteConversation(conv.title, conv.conversation_id);
                        }}
                        className="flex w-full items-center gap-2 rounded-md px-2.5 py-1.5 text-sm text-danger-text transition-colors hover:bg-danger/10"
                      >
                        <Trash2 size={14} />
                        Delete
                      </button>
                    </div>
                )}
              </div>
            );
          })}
      </div>
    </div>
  );
};

export default React.memo(ConversationGroup);
