import { useCallback, useRef, useState } from 'react';
import { cn } from '@/lib/cn';
import type { Conversation } from '@/lib/types';

interface ConversationListProps {
  conversations: Conversation[];
  activeId: string | null;
  isOpen: boolean;
  onClose: () => void;
  onSelect: (id: string) => void;
  onNew: () => void;
  onRename: (id: string, title: string) => void;
  onDelete: (id: string) => void;
  onArchive: (id: string, archived: boolean) => void;
}

interface ContextMenuState {
  conversationId: string;
  x: number;
  y: number;
}

function formatRelativeTime(dateStr: string): string {
  const date = new Date(dateStr);
  const now = new Date();
  const diffMs = now.getTime() - date.getTime();
  const diffMinutes = Math.floor(diffMs / 60_000);
  const diffHours = Math.floor(diffMs / 3_600_000);
  const diffDays = Math.floor(diffMs / 86_400_000);

  if (diffMinutes < 1) return 'Just now';
  if (diffMinutes < 60) return `${diffMinutes}m ago`;
  if (diffHours < 24) return `${diffHours}h ago`;
  if (diffDays === 1) return 'Yesterday';
  if (diffDays < 7) return `${diffDays}d ago`;
  return date.toLocaleDateString();
}

export function ConversationList({
  conversations,
  activeId,
  isOpen,
  onClose,
  onSelect,
  onNew,
  onRename,
  onDelete,
  onArchive,
}: ConversationListProps): React.ReactElement {
  const [searchQuery, setSearchQuery] = useState('');
  const [renamingId, setRenamingId] = useState<string | null>(null);
  const [renameValue, setRenameValue] = useState('');
  const [contextMenu, setContextMenu] = useState<ContextMenuState | null>(null);
  const [deleteConfirmId, setDeleteConfirmId] = useState<string | null>(null);
  const [showArchived, setShowArchived] = useState(false);
  const renameInputRef = useRef<HTMLInputElement>(null);

  const activeConversations = conversations.filter((conversation) => !conversation.archived);
  const archivedConversations = conversations.filter((conversation) => conversation.archived);

  const filteredActive = searchQuery
    ? activeConversations.filter((conversation) =>
        (conversation.title ?? 'Untitled').toLowerCase().includes(searchQuery.toLowerCase()),
      )
    : activeConversations;

  const filteredArchived = searchQuery
    ? archivedConversations.filter((conversation) =>
        (conversation.title ?? 'Untitled').toLowerCase().includes(searchQuery.toLowerCase()),
      )
    : archivedConversations;

  const handleContextMenu = useCallback((event: React.MouseEvent, conversationId: string) => {
    event.preventDefault();
    setContextMenu({ conversationId, x: event.clientX, y: event.clientY });
    setDeleteConfirmId(null);
  }, []);

  const closeContextMenu = useCallback(() => {
    setContextMenu(null);
    setDeleteConfirmId(null);
  }, []);

  const startRename = useCallback(
    (id: string, currentTitle: string | null) => {
      setRenamingId(id);
      setRenameValue(currentTitle ?? '');
      closeContextMenu();
      setTimeout(() => renameInputRef.current?.focus(), 0);
    },
    [closeContextMenu],
  );

  const commitRename = useCallback(() => {
    if (renamingId) {
      const trimmed = renameValue.trim();
      onRename(renamingId, trimmed || 'Untitled');
    }
    setRenamingId(null);
    setRenameValue('');
  }, [onRename, renameValue, renamingId]);

  const cancelRename = useCallback(() => {
    setRenamingId(null);
    setRenameValue('');
  }, []);

  const handleRenameKeyDown = useCallback(
    (event: React.KeyboardEvent<HTMLInputElement>) => {
      if (event.key === 'Enter') commitRename();
      if (event.key === 'Escape') cancelRename();
    },
    [cancelRename, commitRename],
  );

  const confirmDelete = useCallback(
    (id: string) => {
      onDelete(id);
      setDeleteConfirmId(null);
      closeContextMenu();
    },
    [closeContextMenu, onDelete],
  );

  const handleArchiveToggle = useCallback(
    (id: string, archived: boolean) => {
      onArchive(id, archived);
      closeContextMenu();
    },
    [closeContextMenu, onArchive],
  );

  const contextConversation = contextMenu
    ? conversations.find((conversation) => conversation.id === contextMenu.conversationId)
    : null;

  function renderConversationItem(conversation: Conversation): React.ReactElement {
    const isActive = activeId === conversation.id;
    const isRenaming = renamingId === conversation.id;

    return (
      <div key={conversation.id} className="group relative">
        {isRenaming ? (
          <div className="px-3 py-2">
            <input
              ref={renameInputRef}
              value={renameValue}
              onChange={(event) => setRenameValue(event.target.value)}
              onBlur={commitRename}
              onKeyDown={handleRenameKeyDown}
              className="w-full rounded-xl border px-3 py-2 text-sm outline-none"
              style={{
                borderColor: 'var(--color-ms-blue-500)',
                backgroundColor: 'var(--color-surface-2)',
                color: 'var(--color-text)',
              }}
              maxLength={255}
            />
          </div>
        ) : (
          <button
            type="button"
            onClick={() => {
              onSelect(conversation.id);
              if (window.innerWidth < 768) onClose();
            }}
            onDoubleClick={() => startRename(conversation.id, conversation.title)}
            onContextMenu={(event) => handleContextMenu(event, conversation.id)}
            className={cn(
              'w-full rounded-2xl px-3 py-2 text-left text-sm transition-colors',
              isActive ? 'shadow-[var(--shadow-ms-sm)]' : 'hover:bg-white/5',
            )}
            style={{
              backgroundColor: isActive
                ? 'color-mix(in srgb, var(--color-ms-blue-500) 22%, transparent)'
                : 'transparent',
              color: isActive ? 'var(--color-text)' : 'var(--color-text-2)',
            }}
          >
            <span className="block truncate font-medium">{conversation.title ?? 'Untitled'}</span>
            <span className="block text-xs text-[var(--color-muted)]">
              {formatRelativeTime(conversation.updatedAt)}
            </span>
          </button>
        )}
      </div>
    );
  }

  return (
    <>
      {isOpen ? (
        <button
          type="button"
          className="fixed inset-0 z-20 bg-black/45 md:hidden"
          onClick={onClose}
          aria-label="Close conversation sidebar"
        />
      ) : null}

      {contextMenu ? (
        <div className="fixed inset-0 z-10" onClick={closeContextMenu} aria-hidden="true" />
      ) : null}

      <div
        className={cn(
          'fixed inset-y-0 left-0 z-30 flex h-full w-[18.5rem] flex-col border-r px-3 py-3 transition-transform duration-200 md:static md:z-auto',
          isOpen
            ? 'translate-x-0'
            : '-translate-x-full md:w-0 md:min-w-0 md:overflow-hidden md:border-r-0 md:px-0 md:py-0',
        )}
        style={{
          backgroundColor: 'var(--color-surface)',
          borderColor: 'var(--color-border)',
        }}
      >
        <div className="flex items-center justify-between px-1 pb-3">
          <h2 className="text-sm font-medium text-[var(--color-text-2)]">Conversations</h2>
          <button
            type="button"
            onClick={onNew}
            className="rounded-full px-3 py-1 text-xs transition-colors hover:bg-white/5"
            style={{ color: 'var(--color-ms-blue-400)' }}
          >
            + New
          </button>
        </div>

        <div className="pb-3">
          <input
            type="search"
            value={searchQuery}
            onChange={(event) => setSearchQuery(event.target.value)}
            placeholder="Search conversations…"
            className="w-full rounded-2xl border px-3 py-2 text-xs placeholder:text-[var(--color-muted)] focus:outline-none"
            style={{
              backgroundColor: 'var(--color-surface-2)',
              borderColor: 'var(--color-border)',
              color: 'var(--color-text)',
            }}
          />
        </div>

        <div className="flex-1 overflow-y-auto space-y-1">
          {filteredActive.length === 0 && !searchQuery ? (
            <p className="px-1 py-2 text-xs text-[var(--color-muted)]">No conversations yet</p>
          ) : null}
          {filteredActive.length === 0 && searchQuery ? (
            <p className="px-1 py-2 text-xs text-[var(--color-muted)]">
              No results for “{searchQuery}”
            </p>
          ) : null}
          {filteredActive.map((conversation) => renderConversationItem(conversation))}

          {archivedConversations.length > 0 ? (
            <div className="pt-2">
              <button
                type="button"
                onClick={() => setShowArchived((prev) => !prev)}
                className="flex w-full items-center gap-2 px-1 py-1 text-xs text-[var(--color-muted)] transition-colors hover:text-[var(--color-text-2)]"
              >
                <span
                  className={cn('inline-block transition-transform', showArchived && 'rotate-90')}
                >
                  ▶
                </span>
                Archived ({archivedConversations.length})
              </button>
              {showArchived ? (
                <div className="mt-1 space-y-1 opacity-70">
                  {filteredArchived.map((conversation) => renderConversationItem(conversation))}
                </div>
              ) : null}
            </div>
          ) : null}
        </div>
      </div>

      {contextMenu && contextConversation ? (
        <div
          className="fixed z-30 min-w-40 rounded-2xl border py-1 shadow-[var(--shadow-ms-lg)]"
          style={{
            top: contextMenu.y,
            left: contextMenu.x,
            backgroundColor: 'var(--color-surface)',
            borderColor: 'var(--color-border)',
          }}
        >
          <button
            type="button"
            className="w-full px-3 py-2 text-left text-sm text-[var(--color-text-2)] transition-colors hover:bg-white/5"
            onClick={() => startRename(contextConversation.id, contextConversation.title)}
          >
            Rename
          </button>
          <button
            type="button"
            className="w-full px-3 py-2 text-left text-sm text-[var(--color-text-2)] transition-colors hover:bg-white/5"
            onClick={() =>
              handleArchiveToggle(contextConversation.id, !contextConversation.archived)
            }
          >
            {contextConversation.archived ? 'Restore' : 'Archive'}
          </button>
          {deleteConfirmId === contextConversation.id ? (
            <button
              type="button"
              className="w-full px-3 py-2 text-left text-sm text-[var(--color-danger)] transition-colors hover:bg-white/5"
              onClick={() => confirmDelete(contextConversation.id)}
            >
              Confirm delete
            </button>
          ) : (
            <button
              type="button"
              className="w-full px-3 py-2 text-left text-sm text-[var(--color-danger)] transition-colors hover:bg-white/5"
              onClick={() => setDeleteConfirmId(contextConversation.id)}
            >
              Delete…
            </button>
          )}
        </div>
      ) : null}
    </>
  );
}
