'use client';

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

interface ConversationListProps {
  conversations: Conversation[];
  activeId: string | null;
  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;
}

/** Format a date as relative time (e.g. "2h ago", "Yesterday"). */
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,
  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((c) => !c.archived);
  const archivedConversations = conversations.filter((c) => c.archived);

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

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

  const handleContextMenu = useCallback((e: React.MouseEvent, conversationId: string) => {
    e.preventDefault();
    setContextMenu({ conversationId, x: e.clientX, y: e.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('');
  }, [renamingId, renameValue, onRename]);

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

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

  const handleDeleteClick = useCallback((id: string) => {
    setDeleteConfirmId(id);
  }, []);

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

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

  const contextConv = contextMenu
    ? conversations.find((c) => c.id === contextMenu.conversationId)
    : null;

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

    return (
      <div key={conv.id} className="group relative">
        {isRenaming ? (
          <div className="px-3 py-2">
            <input
              ref={renameInputRef}
              value={renameValue}
              onChange={(e) => setRenameValue(e.target.value)}
              onBlur={commitRename}
              onKeyDown={handleRenameKeyDown}
              className="w-full rounded border border-blue-500 bg-surface-elevated px-2 py-0.5 text-sm text-text-primary outline-none"
              maxLength={255}
            />
          </div>
        ) : (
          <button
            type="button"
            onClick={() => onSelect(conv.id)}
            onDoubleClick={() => startRename(conv.id, conv.title)}
            onContextMenu={(e) => handleContextMenu(e, conv.id)}
            className={cn(
              'w-full px-3 py-2 text-left text-sm transition-colors',
              isActive
                ? 'bg-blue-600/20 text-blue-400'
                : 'text-text-secondary hover:bg-surface-elevated',
            )}
          >
            <span className="block truncate">{conv.title ?? 'Untitled'}</span>
            <span className="block text-xs text-text-muted">
              {formatRelativeTime(conv.updatedAt)}
            </span>
          </button>
        )}
      </div>
    );
  }

  return (
    <>
      {/* Backdrop to close context menu */}
      {contextMenu && (
        <div className="fixed inset-0 z-10" onClick={closeContextMenu} aria-hidden="true" />
      )}

      <div className="flex h-full w-64 flex-col border-r border-surface-border bg-surface-card">
        {/* Header */}
        <div className="flex items-center justify-between p-3">
          <h2 className="text-sm font-medium text-text-secondary">Conversations</h2>
          <button
            type="button"
            onClick={onNew}
            className="rounded-md px-2 py-1 text-xs text-blue-400 transition-colors hover:bg-surface-elevated"
          >
            + New
          </button>
        </div>

        {/* Search input */}
        <div className="px-3 pb-2">
          <input
            type="search"
            value={searchQuery}
            onChange={(e) => setSearchQuery(e.target.value)}
            placeholder="Search conversations\u2026"
            className="w-full rounded-md border border-surface-border bg-surface-elevated px-3 py-1.5 text-xs text-text-primary placeholder:text-text-muted focus:border-blue-500 focus:outline-none"
          />
        </div>

        {/* Conversation list */}
        <div className="flex-1 overflow-y-auto">
          {filteredActive.length === 0 && !searchQuery && (
            <p className="px-3 py-2 text-xs text-text-muted">No conversations yet</p>
          )}
          {filteredActive.length === 0 && searchQuery && (
            <p className="px-3 py-2 text-xs text-text-muted">
              No results for &ldquo;{searchQuery}&rdquo;
            </p>
          )}
          {filteredActive.map((conv) => renderConversationItem(conv))}

          {/* Archived section */}
          {archivedConversations.length > 0 && (
            <div className="mt-2">
              <button
                type="button"
                onClick={() => setShowArchived((v) => !v)}
                className="flex w-full items-center gap-1 px-3 py-1 text-xs text-text-muted transition-colors hover:text-text-secondary"
              >
                <span
                  className={cn(
                    'inline-block transition-transform',
                    showArchived ? 'rotate-90' : '',
                  )}
                >
                  &#9658;
                </span>
                Archived ({archivedConversations.length})
              </button>
              {showArchived && (
                <div className="opacity-60">
                  {filteredArchived.map((conv) => renderConversationItem(conv))}
                </div>
              )}
            </div>
          )}
        </div>
      </div>

      {/* Context menu */}
      {contextMenu && contextConv && (
        <div
          className="fixed z-20 min-w-36 rounded-md border border-surface-border bg-surface-card py-1 shadow-lg"
          style={{ top: contextMenu.y, left: contextMenu.x }}
        >
          <button
            type="button"
            className="w-full px-3 py-1.5 text-left text-sm text-text-secondary hover:bg-surface-elevated"
            onClick={() => startRename(contextConv.id, contextConv.title)}
          >
            Rename
          </button>
          <button
            type="button"
            className="w-full px-3 py-1.5 text-left text-sm text-text-secondary hover:bg-surface-elevated"
            onClick={() => handleArchiveToggle(contextConv.id, !contextConv.archived)}
          >
            {contextConv.archived ? 'Unarchive' : 'Archive'}
          </button>
          <hr className="my-1 border-surface-border" />
          {deleteConfirmId === contextConv.id ? (
            <div className="px-3 py-1.5">
              <p className="mb-1.5 text-xs text-red-400">Delete this conversation?</p>
              <div className="flex gap-2">
                <button
                  type="button"
                  className="rounded bg-red-600 px-2 py-0.5 text-xs text-white hover:bg-red-700"
                  onClick={() => confirmDelete(contextConv.id)}
                >
                  Delete
                </button>
                <button
                  type="button"
                  className="rounded px-2 py-0.5 text-xs text-text-muted hover:bg-surface-elevated"
                  onClick={() => setDeleteConfirmId(null)}
                >
                  Cancel
                </button>
              </div>
            </div>
          ) : (
            <button
              type="button"
              className="w-full px-3 py-1.5 text-left text-sm text-red-400 hover:bg-surface-elevated"
              onClick={() => handleDeleteClick(contextConv.id)}
            >
              Delete
            </button>
          )}
        </div>
      )}
    </>
  );
}
