import { useState } from 'react';
import { Archive, MessageSquare, Send, ChevronDown, ChevronRight, RotateCcw, Trash2 } from 'lucide-react';
import type { Chat } from '@/api/types';
import { Button } from '@/components/ui/button';
import { Textarea } from '@/components/ui/textarea';
import { Input } from '@/components/ui/input';
import {
  ContextMenu,
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuSeparator,
  ContextMenuTrigger,
} from '@/components/ui/context-menu';
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogDescription,
} from '@/components/ui/dialog';
import { formatTokens } from '@/lib/format';

interface Props {
  sessionId: string;
  projectId: string;
  chats: Chat[];
  onOpenChat: (chatId: string) => void;
  onSend: (content: string) => void;
  onReopenChat: (chatId: string) => Promise<void>;
  onArchiveChat: (chatId: string) => Promise<void>;
  onRenameChat: (chatId: string, name: string) => Promise<void>;
  onDeleteChat: (chatId: string) => Promise<void>;
}

function relTime(iso: string): string {
  const now = Date.now();
  const t = Date.parse(iso);
  if (Number.isNaN(t)) return '';
  const sec = Math.max(0, Math.floor((now - t) / 1000));
  if (sec < 60) return `${sec}s ago`;
  const min = Math.floor(sec / 60);
  if (min < 60) return `${min}m ago`;
  const hr = Math.floor(min / 60);
  if (hr < 24) return `${hr}h ago`;
  const day = Math.floor(hr / 24);
  return `${day}d ago`;
}

interface ChatRowProps {
  chat: Chat;
  onClick: () => void;
  dimmed?: boolean;
  trailing?: React.ReactNode;
  actions?: React.ReactNode;
  renamingId: string | null;
  renameValue: string;
  setRenameValue: (s: string) => void;
  onFinishRename: () => void;
  onCancelRename: () => void;
  onContextStartRename: () => void;
  onContextArchive: () => void;
  onContextDelete: () => void;
  showContextMenu: boolean;
}

function ChatRow({
  chat,
  onClick,
  dimmed,
  trailing,
  actions,
  renamingId,
  renameValue,
  setRenameValue,
  onFinishRename,
  onCancelRename,
  onContextStartRename,
  onContextArchive,
  onContextDelete,
  showContextMenu,
}: ChatRowProps) {
  const meta: string[] = [relTime(chat.updated_at)];
  if (chat.message_count !== undefined && chat.message_count > 0) {
    meta.push(`${chat.message_count} msg`);
  }
  const tokens = formatTokens(chat.effective_context_tokens);
  if (tokens) meta.push(tokens);
  const preview = chat.last_message_preview;
  const isRenaming = renamingId === chat.id;

  const inner = (
    <button
      type="button"
      onClick={onClick}
      className="w-full flex flex-col gap-0.5 px-3 py-2 hover:bg-muted/50 text-left"
    >
      <div className="flex items-center gap-2 min-w-0">
        <MessageSquare className={`size-3.5 shrink-0 ${dimmed ? 'opacity-40' : 'opacity-70'}`} />
        {isRenaming ? (
          <input
            autoFocus
            value={renameValue}
            onChange={(e) => setRenameValue(e.target.value)}
            onBlur={() => onFinishRename()}
            onKeyDown={(e) => {
              if (e.key === 'Enter') onFinishRename();
              if (e.key === 'Escape') onCancelRename();
            }}
            onClick={(e) => e.stopPropagation()}
            className="bg-transparent border-b border-border text-sm outline-none flex-1 min-w-0"
          />
        ) : (
          <span className={`truncate text-sm flex-1 ${dimmed ? 'text-muted-foreground' : ''}`}>
            {chat.name ?? 'New chat'}
          </span>
        )}
        {trailing && (
          <span className="text-xs text-muted-foreground shrink-0">{trailing}</span>
        )}
        {actions && (
          <div className="flex items-center gap-0.5 shrink-0">{actions}</div>
        )}
      </div>
      <div className="ml-5 text-xs text-muted-foreground tabular-nums">
        {meta.join(' · ')}
      </div>
      {preview && (
        <div className="ml-5 text-xs italic text-muted-foreground truncate">
          {preview}
        </div>
      )}
    </button>
  );

  if (!showContextMenu) return inner;

  return (
    <ContextMenu>
      <ContextMenuTrigger asChild>{inner}</ContextMenuTrigger>
      <ContextMenuContent>
        <ContextMenuItem onSelect={onClick}>Open</ContextMenuItem>
        <ContextMenuItem onSelect={onContextStartRename}>Rename</ContextMenuItem>
        <ContextMenuItem onSelect={onContextArchive}>Archive</ContextMenuItem>
        <ContextMenuSeparator />
        <ContextMenuItem variant="destructive" onSelect={onContextDelete}>
          Delete
        </ContextMenuItem>
      </ContextMenuContent>
    </ContextMenu>
  );
}

export function SessionLandingPage({
  chats,
  onOpenChat,
  onSend,
  onReopenChat,
  onArchiveChat,
  onRenameChat,
  onDeleteChat,
}: Props) {
  const [composerValue, setComposerValue] = useState('');
  const [showArchived, setShowArchived] = useState(false);
  const [renamingId, setRenamingId] = useState<string | null>(null);
  const [renameValue, setRenameValue] = useState('');
  const [archiveConfirm, setArchiveConfirm] = useState<Chat | null>(null);
  const [deleteConfirm, setDeleteConfirm] = useState<Chat | null>(null);
  const [deleteInput, setDeleteInput] = useState('');

  const openChats = chats
    .filter((c) => c.status === 'open')
    .sort((a, b) => new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime());
  const archivedChats = chats
    .filter((c) => c.status === 'archived')
    .sort((a, b) => new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime());

  function handleSend() {
    const text = composerValue.trim();
    if (!text) return;
    onSend(text);
    setComposerValue('');
  }

  function startRename(chat: Chat) {
    setRenamingId(chat.id);
    setRenameValue(chat.name ?? '');
  }

  async function finishRename() {
    if (renamingId && renameValue.trim()) {
      await onRenameChat(renamingId, renameValue.trim());
    }
    setRenamingId(null);
  }

  const deleteExpected = deleteConfirm?.name ?? '';
  const deleteEnabled = deleteConfirm !== null && deleteInput === deleteExpected && deleteExpected.length > 0;

  // TODO: Landing page chat counts are a snapshot at mount. New messages in
  // visible chats won't update the per-row stats until next mount/navigation.
  return (
    <div className="flex flex-col h-full min-h-0">
      <div className="flex-1 overflow-y-auto px-6 py-4 space-y-6">
        {openChats.length > 0 && (
          <div>
            <h3 className="text-xs font-medium text-muted-foreground mb-2">Open chats</h3>
            <ul className="divide-y rounded-md border">
              {openChats.map((chat) => (
                <li key={chat.id}>
                  <ChatRow
                    chat={chat}
                    onClick={() => onOpenChat(chat.id)}
                    renamingId={renamingId}
                    renameValue={renameValue}
                    setRenameValue={setRenameValue}
                    onFinishRename={() => void finishRename()}
                    onCancelRename={() => setRenamingId(null)}
                    onContextStartRename={() => startRename(chat)}
                    onContextArchive={() => setArchiveConfirm(chat)}
                    onContextDelete={() => { setDeleteConfirm(chat); setDeleteInput(''); }}
                    showContextMenu
                    actions={
                      <>
                        <Button
                          variant="ghost"
                          size="icon-sm"
                          aria-label="Archive chat"
                          title="Archive chat"
                          onClick={(e) => {
                            e.stopPropagation();
                            setArchiveConfirm(chat);
                          }}
                        >
                          <Archive size={14} />
                        </Button>
                        <Button
                          variant="ghost"
                          size="icon-sm"
                          aria-label="Delete chat"
                          title="Delete chat"
                          className="text-destructive hover:text-destructive"
                          onClick={(e) => {
                            e.stopPropagation();
                            setDeleteConfirm(chat);
                            setDeleteInput('');
                          }}
                        >
                          <Trash2 size={14} />
                        </Button>
                      </>
                    }
                  />
                </li>
              ))}
            </ul>
          </div>
        )}

        {archivedChats.length > 0 && (
          <div>
            <button
              type="button"
              onClick={() => setShowArchived(!showArchived)}
              className="flex items-center gap-1 text-xs font-medium text-muted-foreground mb-2 hover:text-foreground"
            >
              {showArchived ? <ChevronDown size={12} /> : <ChevronRight size={12} />}
              Archived chats ({archivedChats.length})
            </button>
            {showArchived && (
              <ul className="divide-y rounded-md border">
                {archivedChats.map((chat) => (
                  <li key={chat.id}>
                    <ChatRow
                      chat={chat}
                      onClick={() => void onReopenChat(chat.id)}
                      dimmed
                      trailing={<><RotateCcw size={10} className="inline mr-1" />Restore</>}
                      renamingId={null}
                      renameValue=""
                      setRenameValue={() => {}}
                      onFinishRename={() => {}}
                      onCancelRename={() => {}}
                      onContextStartRename={() => {}}
                      onContextArchive={() => {}}
                      onContextDelete={() => {}}
                      showContextMenu={false}
                    />
                  </li>
                ))}
              </ul>
            )}
          </div>
        )}

        {openChats.length === 0 && archivedChats.length === 0 && (
          <div className="text-sm text-muted-foreground py-8 text-center">
            No chats yet. Type below to start a conversation.
          </div>
        )}
      </div>

      <div className="border-t px-4 py-3 flex items-end gap-2 shrink-0">
        <Textarea
          value={composerValue}
          onChange={(e) => setComposerValue(e.target.value)}
          onKeyDown={(e) => {
            if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) {
              e.preventDefault();
              handleSend();
              return;
            }
            if (e.key === 'Enter' && !e.shiftKey) {
              e.preventDefault();
              handleSend();
            }
          }}
          placeholder="Start a new chat..."
          rows={2}
          className="resize-none min-h-[52px] max-h-[160px]"
        />
        <Button
          onClick={handleSend}
          disabled={!composerValue.trim()}
          size="icon-lg"
          aria-label="Send"
        >
          <Send />
        </Button>
      </div>

      <Dialog open={archiveConfirm !== null} onOpenChange={(open) => { if (!open) setArchiveConfirm(null); }}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Archive chat?</DialogTitle>
            <DialogDescription>
              Moves {archiveConfirm ? `"${archiveConfirm.name ?? 'New chat'}"` : 'this chat'} to the Archived chats section. You can restore it any time.
            </DialogDescription>
          </DialogHeader>
          <div className="flex gap-2 justify-end pt-2">
            <Button variant="outline" onClick={() => setArchiveConfirm(null)}>
              Cancel
            </Button>
            <Button
              onClick={() => {
                if (archiveConfirm) void onArchiveChat(archiveConfirm.id);
                setArchiveConfirm(null);
              }}
            >
              Archive
            </Button>
          </div>
        </DialogContent>
      </Dialog>

      <Dialog open={deleteConfirm !== null} onOpenChange={(open) => { if (!open) { setDeleteConfirm(null); setDeleteInput(''); } }}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Delete chat?</DialogTitle>
            <DialogDescription>
              Type the chat name to confirm:
              {' '}
              <span className="font-mono font-medium text-foreground">{deleteExpected || '(unnamed — cannot type-confirm)'}</span>
            </DialogDescription>
          </DialogHeader>
          <Input
            value={deleteInput}
            onChange={(e) => setDeleteInput(e.target.value)}
            placeholder={deleteExpected}
            disabled={!deleteExpected}
          />
          <div className="text-xs text-muted-foreground">
            This will permanently delete this chat and all its messages. This cannot be undone.
          </div>
          <div className="flex gap-2 justify-end pt-2">
            <Button variant="outline" onClick={() => { setDeleteConfirm(null); setDeleteInput(''); }}>
              Cancel
            </Button>
            <Button
              variant="destructive"
              disabled={!deleteEnabled}
              onClick={() => {
                if (deleteConfirm && deleteEnabled) void onDeleteChat(deleteConfirm.id);
                setDeleteConfirm(null);
                setDeleteInput('');
              }}
            >
              Delete
            </Button>
          </div>
        </DialogContent>
      </Dialog>
    </div>
  );
}
