'use client';
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { useState } from 'react';
import { Trans, useTranslation } from 'react-i18next';
import { useRouter } from 'next/navigation';
import { Handle, Position } from '@xyflow/react';
import { Plus, Trash2, Zap, ClipboardList, Loader2, Globe, RotateCcw, Play, Square, Eye, Archive, ArchiveRestore, MessageSquare, } from 'lucide-react';
import { cn } from '../../../lib/utils.js';
import { ActionButton } from '../../common/action-button/action-button.js';
import { Button } from '../../ui/button.js';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../../ui/tooltip.js';
import { ChatDotIndicator } from '../../features/chat/ChatDotIndicator.js';
import { useTurnStatus } from '../../../hooks/turn-statuses-provider.js';
import { useDeployAction } from '../../../hooks/use-deploy-action.js';
import { useFeatureFlags } from '../../../hooks/feature-flags-context.js';
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from '../../ui/alert-dialog.js';
import { DeleteFeatureDialog } from '../../common/delete-feature-dialog/index.js';
import { featureNodeStateConfig, lifecycleRunningVerbs, lifecyclePhaseBadge, } from './feature-node-state-config.js';
import { getAgentTypeIcon } from './agent-type-icons.js';
import { FeatureSessionsDropdown } from './feature-sessions-dropdown.js';
function AgentIcon({ agentType, className }) {
    const IconComponent = getAgentTypeIcon(agentType);
    return _jsx(IconComponent, { className: className });
}
function getBadgeIcon(data) {
    const config = featureNodeStateConfig[data.state];
    return config.icon;
}
/** Short, friendly label for each action-required gate. */
function getActionRequiredLabel(data, t) {
    if (data.lifecycle === 'requirements')
        return t('featureNode.reviewRequirements');
    if (data.lifecycle === 'implementation')
        return t('featureNode.reviewTechnicalPlan');
    if (data.lifecycle === 'review')
        return t('featureNode.reviewChanges');
    return t('featureNode.review');
}
function getBadgeText(data, t) {
    const config = featureNodeStateConfig[data.state];
    switch (data.state) {
        case 'creating':
            return t('featureNode.creating');
        case 'running':
            return lifecycleRunningVerbs[data.lifecycle];
        case 'done':
            return data.runtime
                ? t('featureNode.completedIn', { runtime: data.runtime })
                : t('featureNode.completed');
        case 'blocked':
            return data.blockedBy
                ? t('featureNode.waitingOn', { blockedBy: data.blockedBy })
                : t('featureNode.blocked');
        case 'pending':
            return t('featureNode.pending');
        case 'action-required':
            return getActionRequiredLabel(data, t);
        case 'error':
            return data.errorMessage ?? t('featureNode.somethingWentWrong');
        default:
            return config.label;
    }
}
export function FeatureNode({ data, selected, }) {
    const { t, i18n } = useTranslation('web');
    const router = useRouter();
    const isRtl = i18n.dir() === 'rtl';
    const targetHandlePos = isRtl ? Position.Right : Position.Left;
    const sourceHandlePos = isRtl ? Position.Left : Position.Right;
    const config = featureNodeStateConfig[data.state];
    const Icon = config.icon;
    const [confirmOpen, setConfirmOpen] = useState(false);
    const [idCopied, setIdCopied] = useState(false);
    const [archiveConfirmOpen, setArchiveConfirmOpen] = useState(false);
    const featureFlags = useFeatureFlags();
    const chatTurnStatus = useTurnStatus(data.featureId);
    const deployTarget = featureFlags.envDeploy && data.repositoryPath && data.branch
        ? {
            targetId: data.featureId,
            targetType: 'feature',
            repositoryPath: data.repositoryPath,
            branch: data.branch,
        }
        : null;
    const deployAction = useDeployAction(deployTarget);
    const isDeployActive = deployAction.status === 'Booting' || deployAction.status === 'Ready';
    const isDeployReady = deployAction.status === 'Ready';
    return (_jsxs("div", { className: "animate-in fade-in group relative duration-300", style: { direction: isRtl ? 'rtl' : 'ltr' }, children: [data.showHandles ? (_jsx(Handle, { type: "target", position: targetHandlePos, isConnectable: false, className: "opacity-0!", style: { top: 70 } })) : null, _jsx("div", { className: "absolute -start-14 top-0 bottom-0 flex items-center justify-center ps-4 pe-3 opacity-0 transition-opacity group-hover:opacity-100", onPointerDown: (e) => e.stopPropagation(), children: _jsxs("div", { className: "flex flex-col items-center gap-2", children: [data.onArchive &&
                            data.featureId &&
                            data.state !== 'deleting' &&
                            data.state !== 'archived' ? (_jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { "aria-label": t('featureNode.archiveFeature'), "data-testid": "feature-node-archive-button", onClick: (e) => {
                                                e.stopPropagation();
                                                setArchiveConfirmOpen(true);
                                            }, className: "bg-card text-muted-foreground flex h-7 w-7 cursor-pointer items-center justify-center rounded-full border shadow-sm transition-colors hover:border-gray-500 hover:text-gray-600", children: _jsx(Archive, { className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { side: "left", children: t('featureNode.archiveFeature') })] }) })) : null, data.onDelete && data.featureId && data.state !== 'deleting' ? (_jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { "aria-label": t('featureNode.deleteFeature'), "data-testid": "feature-node-delete-button", onClick: (e) => {
                                                e.stopPropagation();
                                                setConfirmOpen(true);
                                            }, className: "bg-card text-muted-foreground hover:border-destructive hover:text-destructive flex h-7 w-7 cursor-pointer items-center justify-center rounded-full border shadow-sm transition-colors", children: _jsx(Trash2, { className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { side: "left", children: t('featureNode.deleteFeature') })] }) })) : null, data.onUnarchive && data.featureId && data.state === 'archived' ? (_jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { "aria-label": t('featureNode.unarchiveFeature'), "data-testid": "feature-node-unarchive-button", onClick: (e) => {
                                                e.stopPropagation();
                                                data.onUnarchive?.(data.featureId);
                                            }, className: "bg-card text-muted-foreground hover:border-primary hover:text-primary flex h-7 w-7 cursor-pointer items-center justify-center rounded-full border shadow-sm transition-colors", children: _jsx(ArchiveRestore, { className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { side: "left", children: t('featureNode.unarchiveFeature') })] }) })) : null] }) }), data.onDelete && data.featureId && data.state !== 'deleting' ? (_jsx(DeleteFeatureDialog, { open: confirmOpen, onOpenChange: setConfirmOpen, onConfirm: (cleanup, cascadeDelete, closePr) => {
                    setConfirmOpen(false);
                    data.onDelete?.(data.featureId, cleanup, cascadeDelete, closePr);
                }, isDeleting: false, featureName: data.name ?? 'this feature', featureId: data.featureId, hasChildren: data.hasChildren, hasOpenPr: !!data.pr && data.pr.status === 'Open' })) : null, data.onArchive &&
                data.featureId &&
                data.state !== 'deleting' &&
                data.state !== 'archived' ? (_jsx(AlertDialog, { open: archiveConfirmOpen, onOpenChange: setArchiveConfirmOpen, children: _jsxs(AlertDialogContent, { onCloseAutoFocus: (e) => e.preventDefault(), children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: t('featureNode.archiveConfirmTitle') }), _jsx(AlertDialogDescription, { children: _jsx(Trans, { t: t, i18nKey: "featureNode.archiveConfirmDescription", values: { name: data.name }, components: { strong: _jsx("strong", {}) } }) })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { onClick: () => setArchiveConfirmOpen(false), children: t('featureNode.cancel') }), _jsx(AlertDialogAction, { onClick: () => {
                                        setArchiveConfirmOpen(false);
                                        data.onArchive?.(data.featureId);
                                    }, children: t('featureNode.archive') })] })] }) })) : null, _jsxs("div", { "data-testid": "feature-node-card", "aria-busy": data.state === 'creating' || data.state === 'deleting' ? 'true' : undefined, className: cn('bg-card flex min-h-35 w-97 cursor-pointer flex-col rounded-lg border p-3 shadow-sm transition-[border-color] duration-200 dark:bg-neutral-800/80', data.state === 'action-required' &&
                    'border-s-[3px] border-s-rose-400 dark:border-s-amber-500', data.state === 'action-required' &&
                    selected &&
                    'border-e-rose-400 border-t-rose-400 border-b-rose-400 dark:border-e-amber-500 dark:border-t-amber-500 dark:border-b-amber-500', selected &&
                    data.state !== 'action-required' &&
                    'border-blue-400 dark:border-amber-500/60', data.state === 'deleting' && 'opacity-60', data.state === 'archived' && 'opacity-50'), children: [data.state !== 'creating' ? (_jsx("div", { className: "absolute end-4 top-3", children: _jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("span", { "data-testid": "feature-node-phase-badge", className: "flex items-center gap-1.5", children: [_jsx("span", { className: "text-muted-foreground text-[10px]", children: lifecyclePhaseBadge[data.lifecycle].tooltip }), _jsx("span", { className: cn('h-1.5 w-1.5 -translate-y-px rounded-full', lifecyclePhaseBadge[data.lifecycle].dot) })] }) }), _jsxs(TooltipContent, { side: "right", className: "max-w-56", children: [_jsx("p", { className: "font-semibold", children: lifecyclePhaseBadge[data.lifecycle].tooltip }), _jsx("p", { className: "mt-1 text-xs leading-relaxed text-neutral-500", children: lifecyclePhaseBadge[data.lifecycle].description })] })] }) }) })) : null, _jsxs("div", { className: "flex items-center gap-1.5 pe-24", children: [data.agentType ? (_jsx(AgentIcon, { agentType: data.agentType, className: "h-4 w-4 shrink-0" })) : null, _jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("span", { "data-testid": "feature-node-fast-mode-badge", className: "shrink-0", children: data.fastMode ? (_jsx(Zap, { className: "h-3.5 w-3.5 text-amber-500" })) : (_jsx(ClipboardList, { className: "h-3.5 w-3.5 text-indigo-500" })) }) }), _jsx(TooltipContent, { side: "top", children: data.fastMode ? t('featureNode.fastMode') : t('featureNode.specDriven') })] }) }), _jsx("h3", { className: "min-w-0 truncate text-sm font-bold", children: data.name })] }), data.description ? (_jsx("p", { "data-testid": "feature-node-description", className: "text-muted-foreground mt-1 line-clamp-2 text-xs", children: data.description })) : null, _jsxs("div", { className: "mt-auto pt-2", children: [config.showProgressBar ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "text-muted-foreground flex items-center justify-end text-[10px]", children: _jsxs("span", { children: [data.progress, "%"] }) }), _jsx("div", { "data-testid": "feature-node-progress-bar", className: "bg-muted mt-1.5 h-1 w-full overflow-hidden rounded-full", children: _jsx("div", { className: cn('h-full rounded-full transition-all', config.progressClass), style: { width: `${data.progress}%` } }) })] })) : null, !config.showProgressBar &&
                                ![
                                    'deleting',
                                    'creating',
                                    'running',
                                    'done',
                                    'action-required',
                                    'pending',
                                    'blocked',
                                ].includes(data.state) ? (_jsxs("div", { "data-testid": "feature-node-badge", className: "relative flex min-w-0 items-center gap-1.5 text-xs", children: [(() => {
                                        const BadgeIcon = getBadgeIcon(data);
                                        return _jsx(BadgeIcon, { className: cn('h-3.5 w-3.5 shrink-0', config.badgeClass) });
                                    })(), _jsx("span", { className: cn('translate-y-px truncate text-[11px] font-medium', config.badgeClass), children: getBadgeText(data, t) })] })) : null, _jsxs("div", { className: "mt-1.5 flex min-h-[26px] items-center justify-between gap-2", style: { transform: 'translateY(1px)' }, children: [_jsxs("div", { className: "flex min-w-0 items-center gap-1.5", children: [data.featureId ? (_jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", "data-testid": "feature-node-id", className: "nodrag text-muted-foreground/60 hover:text-muted-foreground flex shrink-0 cursor-pointer items-baseline gap-1 font-mono text-[10px] transition-colors active:scale-95", onClick: (e) => {
                                                                    e.stopPropagation();
                                                                    navigator.clipboard.writeText(data.featureId);
                                                                    setIdCopied(true);
                                                                    setTimeout(() => setIdCopied(false), 1500);
                                                                }, children: idCopied ? (_jsx("span", { className: "text-emerald-500", children: t('featureNode.copied') })) : (data.featureId.slice(0, 6)) }) }), _jsxs(TooltipContent, { side: "top", children: ["Click to copy: ", data.featureId] })] }) })) : null, (data.worktreePath ?? data.repositoryPath) ? (_jsx(FeatureSessionsDropdown, { repositoryPath: data.worktreePath ?? data.repositoryPath })) : null, data.state !== 'creating' && data.state !== 'deleting' && (_jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs(Button, { variant: "ghost", size: "xs", "aria-label": "Open chat", "data-testid": "feature-node-chat-button", onClick: (e) => {
                                                                    e.stopPropagation();
                                                                    router.push(`/feature/${data.featureId}/chat`);
                                                                }, className: "nodrag relative cursor-pointer text-violet-500 hover:text-violet-600 dark:text-violet-400 dark:hover:text-violet-300", children: [_jsx(MessageSquare, { className: "h-3 w-3" }), _jsx(ChatDotIndicator, { status: chatTurnStatus })] }) }), _jsx(TooltipContent, { side: "top", children: _jsx("p", { className: "text-xs", children: t('featureNode.chatWithAgent') }) })] }) })), deployTarget && data.state !== 'deleting' && data.state !== 'creating' ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "bg-border h-3 w-px shrink-0" }), isDeployReady ? (
                                                    /* Ready: Globe + URL — Globe morphs to Stop on hover */
                                                    _jsxs("span", { className: "group/deploy nodrag flex min-w-0 items-center gap-1.5", "data-testid": "feature-node-deploy-button", onClick: (e) => e.stopPropagation(), children: [_jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", "aria-label": t('featureNode.stopDevServer'), className: "flex h-5 shrink-0 cursor-pointer items-center justify-center rounded-full transition-colors", onClick: (e) => {
                                                                                    e.stopPropagation();
                                                                                    deployAction.stop();
                                                                                }, children: deployAction.stopLoading ? (_jsx(Loader2, { className: "h-3.5 w-3.5 animate-spin text-red-500" })) : (_jsxs("span", { className: "relative h-3.5 w-3.5", children: [_jsx(Globe, { className: "absolute inset-0 h-3.5 w-3.5 text-green-600 transition-opacity duration-200 group-hover/deploy:opacity-0 dark:text-green-400" }), _jsx(Square, { className: "absolute inset-0 h-3.5 w-3.5 text-red-500 opacity-0 transition-opacity duration-200 group-hover/deploy:opacity-100 dark:text-red-400" })] })) }) }), _jsx(TooltipContent, { side: "top", children: t('featureNode.stopDevServer') })] }) }), deployAction.url ? (_jsx("a", { href: deployAction.url, target: "_blank", rel: "noopener noreferrer", "data-testid": "feature-node-deployment-indicator", className: "nodrag min-w-0 truncate text-[10px] text-green-700 hover:underline dark:text-green-400", onClick: (e) => e.stopPropagation(), children: deployAction.url })) : null] })) : isDeployActive ? (
                                                    /* Booting: Stop button + "Starting…" */
                                                    _jsxs("span", { className: "nodrag flex min-w-0 items-center gap-1.5", "data-testid": "feature-node-deploy-button", onClick: (e) => e.stopPropagation(), children: [_jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", "aria-label": t('featureNode.stopDevServer'), className: "flex h-5 shrink-0 cursor-pointer items-center justify-center rounded-full text-red-500 transition-colors hover:text-red-600 dark:text-red-400 dark:hover:text-red-300", onClick: (e) => {
                                                                                    e.stopPropagation();
                                                                                    deployAction.stop();
                                                                                }, children: deployAction.stopLoading ? (_jsx(Loader2, { className: "h-3.5 w-3.5 animate-spin" })) : (_jsx(Square, { className: "h-3.5 w-3.5" })) }) }), _jsx(TooltipContent, { side: "top", children: t('featureNode.stopDevServer') })] }) }), _jsx("span", { className: "text-muted-foreground animate-pulse text-[10px]", children: t('featureNode.starting') })] })) : (
                                                    /* Idle / Error: Play or Retry button */
                                                    _jsxs(_Fragment, { children: [_jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("span", { className: cn('nodrag flex shrink-0 items-center', !deployAction.deployError &&
                                                                                    '[&_button]:text-green-600 [&_button]:hover:text-green-700 dark:[&_button]:text-green-400 dark:[&_button]:hover:text-green-300'), "data-testid": "feature-node-deploy-button", onClick: (e) => e.stopPropagation(), children: _jsx(ActionButton, { label: deployAction.deployError
                                                                                        ? t('featureNode.retry')
                                                                                        : t('featureNode.startDevServer'), onClick: deployAction.deploy, loading: deployAction.deployLoading, error: false, icon: deployAction.deployError ? RotateCcw : Play, iconOnly: true, variant: "ghost", size: "icon-xs" }) }) }), _jsx(TooltipContent, { side: "top", children: deployAction.deployError
                                                                                ? t('featureNode.retryDevServer')
                                                                                : t('featureNode.startDevServer') })] }) }), deployAction.deployError ? (_jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("span", { className: "min-w-0 truncate text-[10px] text-red-500", children: t('featureNode.failed') }) }), _jsx(TooltipContent, { side: "top", className: "max-w-64", children: _jsx("p", { className: "text-xs", children: deployAction.deployError }) })] }) })) : null] }))] })) : null] }), data.state === 'deleting' ? (_jsxs("div", { className: "flex items-center gap-1.5 text-xs", children: [_jsx(Loader2, { className: "h-3.5 w-3.5 shrink-0 animate-spin text-gray-400" }), _jsx("span", { className: "text-muted-foreground", children: t('featureNode.deleting') })] })) : data.state === 'creating' ? (_jsxs("div", { className: "flex items-center gap-1.5 text-xs", children: [_jsx(Icon, { className: "h-3.5 w-3.5 shrink-0 animate-spin text-teal-600 dark:text-teal-400" }), _jsx("span", { className: "font-medium text-teal-600 dark:text-teal-400", children: getBadgeText(data, t) })] })) : data.state === 'running' ? (_jsxs("div", { className: "flex items-center gap-1.5 text-xs", children: [_jsx(Icon, { className: "h-3.5 w-3.5 shrink-0 animate-spin text-teal-600 dark:text-teal-400" }), _jsx("span", { className: "font-medium text-teal-600 dark:text-teal-400", children: getBadgeText(data, t) })] })) : data.state === 'action-required' ? (_jsxs(Button, { variant: "default", size: "xs", "aria-label": getActionRequiredLabel(data, t), "data-testid": "feature-node-approve-button", 
                                        // eslint-disable-next-line @typescript-eslint/no-empty-function -- click bubbles to card's onNodeClick
                                        onClick: () => { }, className: "nodrag dark:bg-primary dark:text-primary-foreground dark:hover:bg-primary/90 cursor-pointer bg-neutral-900 text-[11px] text-white hover:bg-neutral-800", children: [_jsx(Eye, { className: "h-3 w-3" }), getActionRequiredLabel(data, t)] })) : data.state === 'error' && data.onRetry ? (_jsxs(Button, { variant: "outline", size: "xs", "aria-label": t('featureNode.retry'), "data-testid": "feature-node-retry-button", onClick: (e) => {
                                            e.stopPropagation();
                                            data.onRetry(data.featureId);
                                        }, className: "nodrag cursor-pointer text-[11px] font-medium", children: [_jsx(RotateCcw, { className: "h-3 w-3" }), t('featureNode.retry')] })) : data.state === 'blocked' ? (_jsxs("div", { className: "flex items-center gap-1.5 text-xs", "data-testid": "feature-node-badge", children: [(() => {
                                                const BadgeIcon = getBadgeIcon(data);
                                                return _jsx(BadgeIcon, { className: cn('h-3.5 w-3.5 shrink-0', config.badgeClass) });
                                            })(), _jsx("span", { className: cn('truncate text-[11px] font-medium', config.badgeClass), children: getBadgeText(data, t) })] })) : data.state === 'done' ? (_jsxs("div", { className: "flex items-center gap-1.5 text-xs", "data-testid": "feature-node-badge", children: [(() => {
                                                const BadgeIcon = getBadgeIcon(data);
                                                return _jsx(BadgeIcon, { className: cn('h-3.5 w-3.5 shrink-0', config.badgeClass) });
                                            })(), _jsx("span", { className: cn('text-[11px] font-medium', config.badgeClass), children: getBadgeText(data, t) })] })) : data.state === 'pending' && data.onStart ? (_jsxs(Button, { variant: "outline", size: "xs", "aria-label": t('featureNode.start'), "data-testid": "feature-node-start-button", onClick: (e) => {
                                            e.stopPropagation();
                                            data.onStart(data.featureId);
                                        }, className: "nodrag cursor-pointer text-[11px] font-medium", children: [_jsx(Play, { className: "h-3 w-3" }), t('featureNode.start')] })) : null] })] })] }), data.onAction && data.state !== 'deleting' ? (_jsx(Handle, { type: "source", position: sourceHandlePos, className: "h-0! w-0! border-0! bg-transparent!", style: { top: 70 }, children: _jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", "aria-label": t('featureNode.addFeature'), "data-testid": "feature-node-action-button", onClick: (e) => {
                                        e.stopPropagation();
                                        data.onAction?.();
                                    }, className: "nodrag absolute start-1/2 top-1/2 flex h-6 w-6 -translate-x-1/2 -translate-y-1/2 cursor-pointer items-center justify-center rounded-full bg-blue-500 text-white opacity-0 shadow-md transition-opacity group-hover:opacity-100 hover:bg-blue-600", children: _jsx(Plus, { className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { side: "right", children: t('featureNode.addFeature') })] }) }) })) : data.showHandles ? (_jsx(Handle, { type: "source", position: sourceHandlePos, isConnectable: false, className: "opacity-0!", style: { top: 70 } })) : null] }));
}
