import { useState } from 'react' import { CircleDot, CheckCircle2, XCircle, Circle, RotateCcw } from 'lucide-react' import { cn } from '@/lib/utils' import type { BranchResponse } from '@/types/branching' type BranchStatus = BranchResponse['status'] interface StatusConfig { icon: React.ElementType textClass: string badgeClass: string borderClass: string label: string } const STATUS_CONFIG: Record = { active: { icon: CircleDot, textClass: 'text-accent', badgeClass: 'bg-accent-dim text-accent-text', borderClass: 'border-accent/50', label: 'Active', }, solved: { icon: CheckCircle2, textClass: 'text-success', badgeClass: 'bg-success-dim text-success', borderClass: 'border-success/30', label: 'Solved', }, dead_end: { icon: XCircle, textClass: 'text-danger', badgeClass: 'bg-danger-dim text-danger', borderClass: 'border-danger/30', label: 'Dead End', }, untried: { icon: Circle, textClass: 'text-muted-foreground', badgeClass: 'bg-elevated text-muted-foreground', borderClass: 'border-default', label: 'Untried', }, revived: { icon: RotateCcw, textClass: 'text-warning', badgeClass: 'bg-warning-dim text-warning', borderClass: 'border-warning/30', label: 'Revived', }, } interface BranchNodeProps { branch: BranchResponse depth: number isActive: boolean onClick: (branchId: string) => void } export function BranchNode({ branch, depth, isActive, onClick }: BranchNodeProps) { const [isHovered, setIsHovered] = useState(false) const config = STATUS_CONFIG[branch.status] const Icon = config.icon const hasDetail = branch.context_summary || branch.status_reason const showExpanded = isHovered && hasDetail && !isActive return (
setIsHovered(true)} onMouseLeave={() => setIsHovered(false)} > {/* Base card — always visible */} {/* Expanded card — floats directly on top of the base card */} {showExpanded && ( <> {/* Visual dim — pointer-events-none so clicks pass through to cards */}
{/* Expanded card positioned over the original */}
)}
) } /** Card header row — shared between base and expanded states */ function CardHeader({ icon: Icon, config, branch, isActive, }: { icon: React.ElementType config: StatusConfig branch: BranchResponse isActive: boolean }) { return (
{branch.label} {config.label}
) } /** Detail content — shared between inline (active) and expanded (hover) */ function BranchDetail({ branch }: { branch: BranchResponse }) { return ( <> {branch.context_summary && ( <> {branch.context_summary.tried.length > 0 && (

Tried:{' '} {branch.context_summary.tried.join(', ')}

)} {branch.context_summary.concluded && (

Result:{' '} {branch.context_summary.concluded}

)} )} {branch.status_reason && (

Reason:{' '} {branch.status_reason}

)}
{branch.step_count} step{branch.step_count !== 1 ? 's' : ''}
) }