'use client';
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { useState, useEffect, useRef, useTransition } from 'react';
import { useTranslation } from 'react-i18next';
import { AlertTriangle, Check, CheckCircle2, Clock, ExternalLink, FileSearch, GitBranch, GitCommitHorizontal, GitMerge, Info, Loader2, Puzzle, RefreshCw, Search, Settings, ShieldCheck, X, Zap, } from 'lucide-react';
import { InlineAttachments } from '../../common/inline-attachments/index.js';
import { PrStatus } from '../../../../../../packages/core/src/domain/generated/output.js';
import { cn } from '../../../lib/utils.js';
import { Badge } from '../../ui/badge.js';
import { Button } from '../../ui/button.js';
import { CiStatusBadge } from '../../common/ci-status-badge/index.js';
import { CometSpinner } from '../../ui/comet-spinner.js';
import { ActionButton } from '../../common/action-button/index.js';
import { useFeatureFlags } from '../../../hooks/feature-flags-context.js';
import { triggerReview } from '../../../app/actions/trigger-review.js';
import { CodeReviewPanel } from '../../features/code-review/code-review-panel.js';
import { featureNodeStateConfig } from '../../common/feature-node/index.js';
import { AgentModelPicker } from '../../features/settings/AgentModelPicker/index.js';
import { getAgentTypeIcon, agentTypeLabels, } from '../../common/feature-node/agent-type-icons.js';
import { getModelMeta } from '../../../lib/model-metadata.js';
import { formatDuration } from '../../../lib/format-duration.js';
import { canSwitchPinnedConfig } from './pinned-config-utils.js';
// ── Primitives ──────────────────────────────────────────────────────
function Section({ icon: Icon, title, children, }) {
    return (_jsxs("div", { className: "px-3 pt-4 pb-1", children: [_jsxs("div", { className: "text-foreground mb-2 flex items-center gap-1.5 text-sm font-semibold tracking-wider uppercase", children: [_jsx(Icon, { className: "size-4 opacity-50" }), title] }), children] }));
}
function Card({ children, className }) {
    return (_jsx("div", { className: cn('bg-muted/60 rounded-md border border-transparent p-3', className), children: children }));
}
function KV({ label, children }) {
    return (_jsxs("div", { className: "flex flex-col gap-0.5", children: [_jsx("span", { className: "text-foreground/40 text-[11px] font-medium tracking-wider uppercase", children: label }), _jsx("span", { className: "text-sm leading-snug", children: children })] }));
}
function Flag({ on, label }) {
    return (_jsxs("span", { className: cn('inline-flex items-center gap-1 rounded px-2 py-0.5 text-xs font-medium', on
            ? 'bg-emerald-500/10 text-emerald-600 dark:text-emerald-400'
            : 'bg-foreground/[0.04] text-foreground/25'), children: [on ? _jsx(Check, { className: "size-3" }) : _jsx(X, { className: "size-3" }), label] }));
}
// ── Helpers ──────────────────────────────────────────────────────────
function formatRelativeTime(timestamp) {
    const now = Date.now();
    const time = typeof timestamp === 'string' ? new Date(timestamp).getTime() : timestamp;
    const diffMs = now - time;
    const diffMin = Math.floor(diffMs / 60000);
    const diffHr = Math.floor(diffMin / 60);
    const diffDay = Math.floor(diffHr / 24);
    if (diffDay > 30)
        return new Date(time).toLocaleDateString(undefined, {
            year: 'numeric',
            month: 'short',
            day: 'numeric',
        });
    if (diffDay > 0)
        return `${diffDay}d ago`;
    if (diffHr > 0)
        return `${diffHr}h ago`;
    if (diffMin > 0)
        return `${diffMin}m ago`;
    return 'just now';
}
function useElapsedTime(startedAt) {
    const [elapsed, setElapsed] = useState(null);
    const intervalRef = useRef(null);
    useEffect(() => {
        if (!startedAt) {
            setElapsed(null);
            return;
        }
        setElapsed(formatDuration(Math.max(0, Date.now() - startedAt)));
        intervalRef.current = setInterval(() => {
            setElapsed(formatDuration(Math.max(0, Date.now() - startedAt)));
        }, 1000);
        return () => {
            if (intervalRef.current)
                clearInterval(intervalRef.current);
        };
    }, [startedAt]);
    return elapsed;
}
const prColor = {
    [PrStatus.Open]: 'text-blue-600 dark:text-blue-400',
    [PrStatus.Merged]: 'text-purple-600 dark:text-purple-400',
    [PrStatus.Closed]: 'text-red-600 dark:text-red-400',
};
export function OverviewTab({ data, pinnedConfig, syncStatus, syncLoading, syncError, onRefreshSync, onRebaseOnMain, rebaseLoading, rebaseError, }) {
    const featureFlags = useFeatureFlags();
    const isCompleted = data.lifecycle === 'maintain';
    const isRunning = data.state === 'running' || data.state === 'action-required';
    const elapsedTime = useElapsedTime(isRunning ? data.startedAt : undefined);
    const config = featureNodeStateConfig[data.state];
    const showSummary = Boolean(data.summary) && !(data.userQuery && data.summary?.trim() === data.userQuery.trim());
    // Code review state
    const [reviewResult, setReviewResult] = useState(null);
    const [reviewError, setReviewError] = useState(null);
    const [isReviewing, startReviewTransition] = useTransition();
    const [isPosting, startPostTransition] = useTransition();
    const showReviewButton = featureFlags.codeReview && data.pr;
    const handleTriggerReview = () => {
        if (!data.pr)
            return;
        setReviewError(null);
        setReviewResult(null);
        startReviewTransition(async () => {
            const result = await triggerReview({
                target: data.pr.url,
                repositoryPath: data.repositoryPath,
                featureId: data.featureId,
            });
            if (result.error) {
                setReviewError(result.error);
            }
            if (result.review) {
                setReviewResult(result.review);
            }
        });
    };
    const handlePostToGitHub = (reviewId) => {
        startPostTransition(async () => {
            try {
                const res = await fetch(`/api/code-reviews/${reviewId}/post`, { method: 'POST' });
                if (!res.ok) {
                    const body = await res.json().catch(() => ({ error: 'Failed to post review' }));
                    setReviewError(body.error ?? 'Failed to post review to GitHub');
                    return;
                }
                const posted = await res.json();
                setReviewResult(posted);
            }
            catch (err) {
                setReviewError(err instanceof Error ? err.message : 'Failed to post review');
            }
        });
    };
    return (_jsxs("div", { "data-testid": "feature-drawer-status", className: "pb-4", children: [!isCompleted && data.progress > 0 ? (_jsx("div", { "data-testid": "feature-drawer-progress", className: "px-3 pb-2", children: _jsx("div", { className: "bg-foreground/[0.06] h-1.5 w-full overflow-hidden rounded-full", children: _jsx("div", { className: cn('h-full rounded-full transition-all', config.progressClass), style: { width: `${data.progress}%` } }) }) })) : null, data.oneLiner || data.userQuery || showSummary ? (_jsx(Section, { icon: Info, title: "Description", children: _jsxs(Card, { className: "flex flex-col gap-2", children: [data.oneLiner ? _jsx(KV, { label: "One-Liner", children: data.oneLiner }) : null, data.userQuery ? (_jsx(KV, { label: "Query", children: _jsx(InlineAttachments, { text: data.userQuery }) })) : null, showSummary ? (_jsx(KV, { label: "Summary", children: _jsx("span", { className: "leading-snug", children: data.summary }) })) : null] }) })) : null, data.pr ? (_jsxs(Section, { icon: GitCommitHorizontal, title: "Pull Request", children: [_jsx(Card, { children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs("a", { href: data.pr.url, target: "_blank", rel: "noopener noreferrer", className: "text-primary inline-flex items-center gap-1 text-sm font-semibold hover:underline", children: ["#", data.pr.number, " ", _jsx(ExternalLink, { className: "size-3" })] }), _jsx("span", { className: cn('text-xs font-semibold', prColor[data.pr.status]), children: data.pr.status }), data.pr.mergeable === false ? (_jsxs("span", { className: "inline-flex items-center gap-1 text-xs font-medium text-orange-600 dark:text-orange-400", children: [_jsx(AlertTriangle, { className: "size-3 shrink-0" }), " Conflicts"] })) : null, data.pr.ciStatus && data.hideCiStatus !== true ? (_jsx(CiStatusBadge, { status: data.pr.ciStatus })) : null, showReviewButton ? (_jsxs(Button, { size: "xs", variant: "outline", className: "ml-auto", onClick: handleTriggerReview, disabled: isReviewing, children: [isReviewing ? (_jsx(Loader2, { className: "mr-1 h-3 w-3 animate-spin" })) : (_jsx(Search, { className: "mr-1 h-3 w-3" })), isReviewing ? 'Reviewing...' : 'Review PR'] })) : null, !showReviewButton && data.pr.commitHash ? (_jsx("code", { className: "text-foreground/40 ml-auto font-mono text-[11px]", children: data.pr.commitHash.slice(0, 7) })) : null] }) }), reviewResult || reviewError || isReviewing ? (_jsx("div", { className: "mt-2", children: _jsx(CodeReviewPanel, { review: reviewResult ?? undefined, loading: isReviewing, error: reviewError ?? undefined, onPostToGitHub: handlePostToGitHub, postingInProgress: isPosting }) })) : null] })) : null, _jsxs("div", { className: "grid grid-cols-2 gap-2 px-3 pb-1", children: [data.branch ? (_jsx(Card, { children: _jsxs(KV, { label: "Branch", children: [_jsxs("span", { className: "inline-flex items-center gap-1", children: [_jsx(GitBranch, { className: "text-foreground/30 size-3 shrink-0" }), _jsx("code", { className: "font-mono text-[11px]", children: data.branch })] }), data.baseBranch ? (_jsxs("span", { className: "text-foreground/30 block text-[10px]", children: ["from ", data.baseBranch] })) : null] }) })) : null, data.agentType || data.modelId ? (_jsx(Card, { children: _jsx(KV, { label: "Agent", children: _jsxs("span", { className: "inline-flex items-center gap-1.5", children: [data.agentType
                                        ? (() => {
                                            const I = getAgentTypeIcon(data.agentType);
                                            return _jsx(I, { className: "size-3.5 shrink-0 opacity-50" });
                                        })()
                                        : null, data.agentType ? (_jsx("span", { children: agentTypeLabels[data.agentType] ??
                                            data.agentType })) : null, data.agentType && data.modelId ? (_jsx("span", { className: "text-foreground/20", children: "/" })) : null, data.modelId ? (_jsx("span", { className: "text-foreground/50 text-[12px]", children: getModelMeta(data.modelId).displayName || data.modelId })) : null] }) }) })) : null, data.createdAt ? (_jsx(Card, { children: _jsx(KV, { label: "Created", children: _jsxs("span", { className: "inline-flex items-center gap-1", children: [_jsx(Clock, { className: "text-foreground/30 size-3 shrink-0" }), formatRelativeTime(data.createdAt)] }) }) })) : null, data.fastMode ? (_jsx(Card, { children: _jsx(KV, { label: "Mode", children: _jsxs("span", { className: "inline-flex items-center gap-1 text-amber-600 dark:text-amber-400", children: [_jsx(Zap, { className: "size-3.5" }), " Fast"] }) }) })) : null, data.runtime || elapsedTime ? (_jsx(Card, { children: _jsx(KV, { label: data.runtime ? 'Runtime' : 'Elapsed', children: _jsxs("span", { className: "inline-flex items-center gap-1", children: [_jsx(Clock, { className: "text-foreground/30 size-3 shrink-0" }), data.runtime ?? elapsedTime] }) }) })) : null] }), data.blockedBy || data.errorMessage ? (_jsx(Section, { icon: AlertTriangle, title: "Issues", children: _jsxs(Card, { className: "border-destructive/20 bg-destructive/5", children: [data.blockedBy ? _jsx(KV, { label: "Blocked By", children: data.blockedBy }) : null, data.errorMessage ? (_jsx(KV, { label: "Error", children: _jsx("span", { className: "text-destructive", children: data.errorMessage }) })) : null] }) })) : null, onRebaseOnMain && data.branch && onRefreshSync ? (_jsx(Section, { icon: RefreshCw, title: "Branch Sync", children: _jsx(SyncCard, { syncStatus: syncStatus ?? null, syncLoading: syncLoading ?? false, syncError: syncError ?? null, onRefreshSync: onRefreshSync, onRebaseOnMain: onRebaseOnMain, rebaseLoading: rebaseLoading ?? false, rebaseError: rebaseError ?? null }) })) : null, _jsx(SettingsBlock, { data: data, pinnedConfig: pinnedConfig }), data.injectedSkills?.length ? _jsx(InjectedSkillsSection, { skills: data.injectedSkills }) : null] }));
}
// ── Sync card ───────────────────────────────────────────────────────
function SyncCard({ syncStatus, syncLoading, syncError, onRefreshSync, onRebaseOnMain, rebaseLoading, rebaseError, }) {
    const { t } = useTranslation('web');
    const isBehind = syncStatus != null && syncStatus.behind > 0;
    const isUpToDate = syncStatus?.behind === 0;
    const base = syncStatus?.baseBranch ?? 'main';
    return (_jsxs(Card, { children: [_jsxs("div", { "data-testid": "branch-sync-status", className: "flex items-center justify-between", children: [_jsx("div", { className: "flex items-center gap-1.5 text-[13px]", children: syncLoading && !syncStatus ? (_jsxs(_Fragment, { children: [_jsx(CometSpinner, { size: "sm" }), _jsx("span", { className: "text-foreground/40", children: "Checking..." })] })) : syncError ? (_jsxs(_Fragment, { children: [_jsx(AlertTriangle, { className: "size-3.5 text-red-500" }), _jsx("span", { className: "text-destructive text-xs", children: syncError })] })) : rebaseLoading ? (_jsxs(_Fragment, { children: [_jsx(CometSpinner, { size: "sm" }), _jsxs("span", { children: ["Rebasing on ", _jsx("code", { className: "font-mono text-[11px]", children: base }), "..."] })] })) : isBehind ? (_jsxs(_Fragment, { children: [_jsx(AlertTriangle, { className: "size-3.5 text-orange-500" }), _jsxs("span", { children: [syncStatus.behind, " behind ", _jsx("code", { className: "font-mono text-[11px]", children: base }), syncStatus.ahead > 0 ? (_jsxs("span", { className: "text-foreground/30 ml-1 text-[11px]", children: ["\u00B7 ", syncStatus.ahead, " ahead"] })) : null] })] })) : isUpToDate ? (_jsxs(_Fragment, { children: [_jsx(CheckCircle2, { className: "size-3.5 text-green-500" }), _jsxs("span", { children: ["Up to date \u00B7 ", _jsx("code", { className: "font-mono text-[11px]", children: base }), syncStatus.ahead > 0 ? (_jsxs("span", { className: "text-foreground/30 ml-1 text-[11px]", children: ["\u00B7 ", syncStatus.ahead, " ahead"] })) : null] })] })) : null }), (syncStatus || syncError) && !rebaseLoading ? (_jsx("button", { onClick: onRefreshSync, disabled: syncLoading, className: "text-foreground/30 hover:text-foreground/60 hover:bg-foreground/5 inline-flex size-6 items-center justify-center rounded-sm disabled:opacity-50", "aria-label": t('branchSyncStatus.refreshSyncStatus'), children: _jsx(RefreshCw, { className: cn('size-3', syncLoading && 'animate-spin') }) })) : null] }), isBehind && !rebaseLoading ? (_jsx("div", { className: "pt-2", children: _jsx(ActionButton, { label: t('branchSyncStatus.rebaseOnMain'), onClick: onRebaseOnMain, loading: false, error: !!rebaseError, icon: GitMerge, variant: "outline", size: "sm" }) })) : null, rebaseError ? _jsx("p", { className: "text-destructive pt-1 text-[11px]", children: rebaseError }) : null] }));
}
// ── Settings ────────────────────────────────────────────────────────
function PinnedConfigCard({ pinnedConfig }) {
    const AgentIcon = getAgentTypeIcon(pinnedConfig.agentType);
    const modelName = pinnedConfig.modelId
        ? getModelMeta(pinnedConfig.modelId).displayName || pinnedConfig.modelId
        : 'No model selected';
    return (_jsxs(Card, { "data-testid": "feature-pinned-config-card", className: "flex flex-col gap-3", children: [_jsxs("div", { className: "flex flex-col gap-1", children: [_jsxs("div", { className: "text-foreground/40 flex items-center gap-1 text-[10px] font-medium tracking-wider uppercase", children: [_jsx(Settings, { className: "size-3" }), " Pinned Execution"] }), _jsxs("div", { className: "flex items-center gap-2 text-sm", children: [_jsx(AgentIcon, { className: "size-4 shrink-0 opacity-60" }), _jsx("span", { className: "font-medium", children: agentTypeLabels[pinnedConfig.agentType] ??
                                    pinnedConfig.agentType }), _jsx("span", { className: "text-foreground/20", children: "/" }), _jsx("span", { className: "text-foreground/60", children: modelName })] }), _jsx("p", { className: "text-muted-foreground text-xs", children: "Change the pinned agent and model before the next start, approval, or retry." })] }), _jsx(AgentModelPicker, { initialAgentType: pinnedConfig.agentType, initialModel: pinnedConfig.modelId, agentType: pinnedConfig.agentType, model: pinnedConfig.modelId, onSave: pinnedConfig.onSave, saveError: pinnedConfig.error, saving: pinnedConfig.saving, disabled: pinnedConfig.saving, mode: "settings" })] }));
}
function SettingsBlock({ data, pinnedConfig, }) {
    const hasSettings = data.approvalGates != null ||
        data.push != null ||
        data.openPr != null ||
        data.ciWatchEnabled != null ||
        data.enableEvidence != null ||
        data.forkAndPr != null ||
        data.commitSpecs != null ||
        data.injectSkills != null;
    const showPinnedConfig = pinnedConfig != null && canSwitchPinnedConfig(data.state);
    if (!hasSettings && !showPinnedConfig)
        return null;
    return (_jsx(Section, { icon: Settings, title: "Settings", children: _jsxs("div", { className: "flex flex-col gap-2", children: [showPinnedConfig ? _jsx(PinnedConfigCard, { pinnedConfig: pinnedConfig }) : null, hasSettings ? (_jsxs("div", { className: "grid grid-cols-3 gap-2", children: [data.approvalGates ? (_jsxs(Card, { children: [_jsxs("div", { className: "text-foreground/40 mb-1.5 flex items-center gap-1 text-[10px] font-medium tracking-wider uppercase", children: [_jsx(ShieldCheck, { className: "size-3" }), " Approve"] }), _jsxs("div", { className: "flex flex-col gap-0.5", children: [_jsx(Flag, { on: data.approvalGates.allowPrd, label: "PRD" }), _jsx(Flag, { on: data.approvalGates.allowPlan, label: "Plan" }), _jsx(Flag, { on: data.approvalGates.allowMerge, label: "Merge" })] })] })) : null, data.enableEvidence != null ? (_jsxs(Card, { children: [_jsxs("div", { className: "text-foreground/40 mb-1.5 flex items-center gap-1 text-[10px] font-medium tracking-wider uppercase", children: [_jsx(FileSearch, { className: "size-3" }), " Evidence"] }), _jsxs("div", { className: "flex flex-col gap-0.5", children: [_jsx(Flag, { on: data.enableEvidence, label: "Collect" }), data.commitEvidence != null ? (_jsx(Flag, { on: data.commitEvidence, label: "Add to PR" })) : null] })] })) : null, data.injectSkills != null ? (_jsxs(Card, { children: [_jsxs("div", { className: "text-foreground/40 mb-1.5 flex items-center gap-1 text-[10px] font-medium tracking-wider uppercase", children: [_jsx(Puzzle, { className: "size-3" }), " Skills"] }), _jsx("div", { className: "flex flex-col gap-0.5", children: _jsx(Flag, { on: data.injectSkills, label: "Inject" }) })] })) : null, data.push != null ||
                            data.openPr != null ||
                            data.ciWatchEnabled != null ||
                            data.commitSpecs != null ||
                            data.forkAndPr != null ? (_jsxs(Card, { children: [_jsxs("div", { className: "text-foreground/40 mb-1.5 flex items-center gap-1 text-[10px] font-medium tracking-wider uppercase", children: [_jsx(GitBranch, { className: "size-3" }), " Git"] }), _jsxs("div", { className: "flex flex-col gap-0.5", children: [data.push != null ? _jsx(Flag, { on: data.push, label: "Push" }) : null, data.openPr != null ? _jsx(Flag, { on: data.openPr, label: "PR" }) : null, data.ciWatchEnabled != null ? (_jsx(Flag, { on: data.ciWatchEnabled, label: "Watch" })) : null, data.commitSpecs != null ? _jsx(Flag, { on: data.commitSpecs, label: "Specs" }) : null, data.forkAndPr != null ? _jsx(Flag, { on: data.forkAndPr, label: "Fork" }) : null] })] })) : null] })) : null] }) }));
}
// ── Injected Skills ────────────────────────────────────────────────
function InjectedSkillsSection({ skills }) {
    return (_jsx(Section, { icon: Puzzle, title: "Feature Skills", children: _jsx("div", { className: "flex flex-wrap gap-1.5", children: skills.map((name) => (_jsx(Badge, { variant: "secondary", children: name }, name))) }) }));
}
