import { useMemo } from 'react';
import { Clock, Cpu, Hash, Layers, RefreshCw, X } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { cn } from '@/lib/utils';
import type { Message } from '@/api/types';

interface TurnEntry {
  message: Message;
  turnNumber: number;
  elapsed: string;
  toolCallCount: number;
}

interface Props {
  messages: Message[];
  chatId: string;
  onClose: () => void;
  onScrollToMessage: (messageId: string) => void;
}

function formatElapsed(startedAt: string | null, finishedAt: string | null): string {
  if (!startedAt || !finishedAt) return '—';
  const start = new Date(startedAt).getTime();
  const end = new Date(finishedAt).getTime();
  if (Number.isNaN(start) || Number.isNaN(end)) return '—';
  const ms = end - start;
  if (ms < 0) return '—';
  if (ms < 1000) return `${ms}ms`;
  if (ms < 60_000) return `${Math.round(ms / 1000)}s`;
  const mins = Math.floor(ms / 60_000);
  const secs = Math.round((ms % 60_000) / 1000);
  return `${mins}m ${secs}s`;
}

/**
 * SessionTimeline — vertical timeline of assistant turns in a chat.
 *
 * Renders a side-panel overlay with each turn's model, tokens, duration,
 * and tool-call count. Clicking a turn scrolls the main chat to that
 * message. The latest turn shows a "Scroll to latest" restore button.
 */
export function SessionTimeline({ messages, onClose, onScrollToMessage }: Props) {
  const turns = useMemo<TurnEntry[]>(() => {
    const assistantMsgs = messages.filter(
      (m) => m.role === 'assistant' && m.status === 'complete',
    );
    return assistantMsgs.map((message, i) => ({
      message,
      turnNumber: i + 1,
      elapsed: formatElapsed(message.started_at, message.finished_at),
      toolCallCount: message.tool_calls?.length ?? 0,
    }));
  }, [messages]);

  const latestTurnId = turns.length > 0 ? turns[turns.length - 1]!.message.id : null;

  return (
    <div className="absolute inset-y-0 right-0 w-80 z-20 bg-background border-l border-border shadow-xl flex flex-col overflow-hidden">
      {/* Header */}
      <div className="flex items-center justify-between px-3 py-2.5 border-b border-border shrink-0">
        <h3 className="text-sm font-semibold">Session Timeline</h3>
        <Button variant="ghost" size="icon-xs" onClick={onClose} aria-label="Close timeline">
          <X size={14} />
        </Button>
      </div>

      {/* Timeline entries */}
      <div className="flex-1 overflow-y-auto px-3 py-3">
        {turns.length === 0 ? (
          <div className="text-xs text-muted-foreground text-center py-8">
            No assistant turns yet.
          </div>
        ) : (
          <div className="relative">
            {turns.map((turn, i) => {
              const isLatest = turn.message.id === latestTurnId;
              return (
                <div key={turn.message.id} className="relative flex gap-3 pb-4 last:pb-0">
                  {/* Vertical connector line */}
                  {i < turns.length - 1 && (
                    <div className="absolute left-[11px] top-5 bottom-0 w-px bg-border" />
                  )}

                  {/* Timeline dot button */}
                  <button
                    type="button"
                    onClick={() => onScrollToMessage(turn.message.id)}
                    className="relative flex-shrink-0 mt-1 cursor-pointer focus:outline-none focus-visible:ring-2 focus-visible:ring-ring rounded-full"
                    aria-label={`Scroll to turn ${turn.turnNumber}`}
                  >
                    <div
                      className={cn(
                        'size-[22px] rounded-full border-2 flex items-center justify-center',
                        isLatest
                          ? 'border-primary bg-primary/10'
                          : 'border-muted-foreground/30 bg-background',
                      )}
                    >
                      <div
                        className={cn(
                          'size-2 rounded-full',
                          isLatest ? 'bg-primary' : 'bg-muted-foreground/50',
                        )}
                      />
                    </div>
                  </button>

                  {/* Content card */}
                  <div className="flex-1 min-w-0">
                    <div
                      className="rounded-lg border border-border bg-card p-2.5 cursor-pointer hover:bg-muted/40 transition-colors"
                      onClick={() => onScrollToMessage(turn.message.id)}
                    >
                      {/* Turn number + latest badge */}
                      <div className="flex items-center justify-between mb-1.5">
                        <span className="text-xs font-semibold text-foreground">
                          Turn {turn.turnNumber}
                        </span>
                        {isLatest && (
                          <span className="text-[10px] font-medium text-primary bg-primary/10 px-1.5 py-0.5 rounded-full leading-none">
                            Latest
                          </span>
                        )}
                      </div>

                      {/* Model name */}
                      <div className="flex items-center gap-1.5 text-xs text-muted-foreground mb-1.5">
                        <Cpu size={11} className="shrink-0" />
                        <span className="truncate">{turn.message.model ?? 'Unknown model'}</span>
                      </div>

                      {/* Token count with breakdown */}
                      {turn.message.tokens_used != null && (
                        <div className="flex items-center gap-1.5 text-xs text-muted-foreground mb-1 flex-wrap">
                          <Hash size={11} className="shrink-0" />
                          <span>{turn.message.tokens_used.toLocaleString()} total</span>
                          {turn.message.cache_tokens != null && turn.message.cache_tokens > 0 && (
                            <span className="text-blue-500 dark:text-blue-400">
                              ({turn.message.cache_tokens.toLocaleString()} cache)
                            </span>
                          )}
                          {turn.message.reasoning_tokens != null && turn.message.reasoning_tokens > 0 && (
                            <span className="text-amber-500 dark:text-amber-400">
                              ({turn.message.reasoning_tokens.toLocaleString()} reasoning)
                            </span>
                          )}
                        </div>
                      )}

                      {/* Duration + tool calls */}
                      <div className="flex items-center gap-3 text-xs text-muted-foreground">
                        <span className="inline-flex items-center gap-1">
                          <Clock size={11} />
                          {turn.elapsed}
                        </span>
                        {turn.toolCallCount > 0 && (
                          <span className="inline-flex items-center gap-1">
                            <Layers size={11} />
                            {turn.toolCallCount} tool call{turn.toolCallCount !== 1 ? 's' : ''}
                          </span>
                        )}
                      </div>
                    </div>

                    {/* Restore button for latest turn */}
                    {isLatest && (
                      <button
                        type="button"
                        onClick={(e) => {
                          e.stopPropagation();
                          onScrollToMessage(turn.message.id);
                        }}
                        className="mt-1.5 w-full inline-flex items-center justify-center gap-1 text-[11px] font-medium text-primary hover:text-primary/80 transition-colors py-1 rounded-md hover:bg-primary/5"
                      >
                        <RefreshCw size={11} />
                        Scroll to latest
                      </button>
                    )}
                  </div>
                </div>
              );
            })}
          </div>
        )}
      </div>
    </div>
  );
}
