import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { useState } from "react";
import { AlertTriangle, CheckCircle2, ChevronLeft, CircleDollarSign, ClipboardList, FolderTree, Info, Plus, Timer, } from "lucide-react";
import { PageHeader } from "../../components/PageHeader";
import { Button } from "../../components/ui/button";
import { Popover, PopoverContent, PopoverTrigger, } from "../../components/ui/popover";
import { getTaskStatusLabel, normalizeTaskStatus } from "../taskStatus";
const EMPTY_COUNTS = {
    total: 0,
    todo: 0,
    waiting: 0,
    inProgress: 0,
    review: 0,
    done: 0,
};
const DEFAULT_COST_LIMIT = 25;
const STATE_STOPS = [
    {
        key: "todo",
        label: "To do",
        segmentClassName: "bg-neutral-grey-10",
        swatchClassName: "bg-neutral-grey-10",
    },
    {
        key: "waiting",
        label: "Waiting",
        segmentClassName: "bg-feedback-orange",
        swatchClassName: "bg-feedback-orange",
    },
    {
        key: "inProgress",
        label: "In progress",
        segmentClassName: "bg-feedback-blue",
        swatchClassName: "bg-feedback-blue",
    },
    {
        key: "review",
        label: "Review",
        segmentClassName: "bg-highlight-100",
        swatchClassName: "bg-highlight-100",
    },
    {
        key: "done",
        label: "Done",
        segmentClassName: "bg-feedback-green",
        swatchClassName: "bg-feedback-green",
    },
];
const ATTENTION_STOPS = [
    {
        key: "blocked",
        label: "Blocked",
        swatchClassName: "bg-feedback-orange",
    },
    {
        key: "approval",
        label: "Approval",
        swatchClassName: "bg-highlight-100",
    },
    {
        key: "input",
        label: "Input",
        swatchClassName: "bg-feedback-blue",
    },
    {
        key: "failed",
        label: "Failed",
        swatchClassName: "bg-feedback-red",
    },
    {
        key: "budget",
        label: "Budget",
        swatchClassName: "bg-feedback-orange-light",
    },
    {
        key: "capacity",
        label: "Capacity",
        swatchClassName: "bg-neutral-grey-50",
    },
];
function aggregateTaskCounts(selectedProjectTaskCounts, subprojects, taskCountsByProjectId) {
    if (subprojects.length === 0)
        return selectedProjectTaskCounts;
    return subprojects.reduce((acc, subproject) => {
        const counts = taskCountsByProjectId[subproject.project.projectId] || EMPTY_COUNTS;
        return {
            total: acc.total + counts.total,
            todo: acc.todo + counts.todo,
            waiting: acc.waiting + counts.waiting,
            inProgress: acc.inProgress + counts.inProgress,
            review: acc.review + counts.review,
            done: acc.done + counts.done,
        };
    }, { ...selectedProjectTaskCounts });
}
function aggregateAttention(selectedProjectAttention, subprojects) {
    return subprojects.reduce((acc, subproject) => {
        const attention = subproject.overview?.attention;
        if (!attention)
            return acc;
        return {
            total: acc.total + attention.total,
            blocked: acc.blocked + attention.blocked,
            approval: acc.approval + attention.approval,
            input: acc.input + attention.input,
            failed: acc.failed + attention.failed,
            budget: acc.budget + attention.budget,
            capacity: (acc.capacity ?? 0) + (attention.capacity ?? 0),
        };
    }, {
        total: selectedProjectAttention?.total ?? 0,
        blocked: selectedProjectAttention?.blocked ?? 0,
        approval: selectedProjectAttention?.approval ?? 0,
        input: selectedProjectAttention?.input ?? 0,
        failed: selectedProjectAttention?.failed ?? 0,
        budget: selectedProjectAttention?.budget ?? 0,
        capacity: selectedProjectAttention?.capacity ?? 0,
    });
}
export function formatCurrency(value) {
    return `$${value.toFixed(2)}`;
}
export function formatPercent(value) {
    return `${Math.round(value)}%`;
}
function getAttentionLabel(reason) {
    return (ATTENTION_STOPS.find((stop) => stop.key === reason)?.label ?? "Attention");
}
function getTaskReference(task) {
    return task.taskKey?.trim() || task.taskId.slice(0, 8).toUpperCase();
}
function getAttentionReasonForTask(task) {
    const normalizedStatus = normalizeTaskStatus(task.status, task.executionState);
    if (normalizedStatus === "Done")
        return null;
    switch (task.executionAttentionReason) {
        case "blocked":
        case "approval":
        case "input":
        case "failed":
        case "budget":
            return task.executionAttentionReason;
    }
    switch (task.executionState) {
        case "WaitingForDependency":
            return "blocked";
        case "WaitingForApproval":
        case "WaitingForToolApproval":
            return "approval";
        case "Questions":
        case "WaitingForInput":
        case "WaitingForUser":
            return "input";
        case "AgentError":
            return "failed";
        case "WaitingForBudget":
            return "budget";
        case "WaitingForCapacity":
            return "capacity";
    }
    if (normalizedStatus === "Review")
        return "approval";
    return null;
}
function buildAttentionTickets(groups) {
    return groups.flatMap((group) => group.tasks.flatMap((task) => {
        const reason = getAttentionReasonForTask(task);
        if (!reason)
            return [];
        const normalizedStatus = normalizeTaskStatus(task.status, task.executionState);
        return [
            {
                projectId: group.projectId,
                projectTitle: group.projectTitle,
                taskId: task.taskId,
                taskReference: getTaskReference(task),
                title: task.title,
                reason,
                statusLabel: getTaskStatusLabel(normalizedStatus),
            },
        ];
    }));
}
export function KpiTile(props) {
    const { icon, label, value, detail, testId } = props;
    return (_jsxs("div", { className: "border-border-default flex min-h-[112px] flex-col justify-between rounded-md border bg-white p-4", "data-testid": testId, children: [_jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsx("div", { className: "text-neutral-grey-50 text-[10px] leading-none font-bold tracking-wider uppercase", children: label }), _jsx("div", { className: "bg-neutral-grey-5 text-neutral-grey-50 flex size-8 items-center justify-center rounded-md", children: icon })] }), _jsxs("div", { children: [_jsx("div", { className: "text-neutral-grey-100 text-2xl leading-tight font-medium", children: value }), _jsx("div", { className: "text-neutral-grey-50 mt-1 text-xs", children: detail })] })] }));
}
function AttentionSummaryHeader(props) {
    const { attentionTotal, attentionTickets, detailsLoading = false, onSelectTicket, } = props;
    const [open, setOpen] = useState(false);
    const content = (_jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "bg-neutral-grey-5 text-neutral-grey-50 flex size-8 items-center justify-center rounded-md", children: _jsx(AlertTriangle, { className: "size-4", strokeWidth: 1.5 }) }), _jsxs("div", { children: [_jsx("h2", { className: "text-neutral-grey-100 text-base font-medium", children: "Attention" }), _jsx("p", { className: "text-neutral-grey-50 text-xs", children: "Work that needs a human or system unblock" })] })] }), _jsx("div", { className: "text-neutral-grey-100 text-xl font-medium", children: attentionTotal })] }));
    if (attentionTotal <= 0) {
        return content;
    }
    return (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx("button", { type: "button", className: "hover:bg-neutral-grey-5 focus-visible:ring-component-suggestions -m-2 block w-full rounded-md p-2 text-left transition-colors outline-none focus-visible:ring-2", "aria-label": `Show ${attentionTotal} attention ticket${attentionTotal === 1 ? "" : "s"}`, "data-testid": "taskboard-attention-summary-trigger", children: content }) }), _jsxs(PopoverContent, { align: "end", className: "w-96 p-0", sideOffset: 8, children: [_jsxs("div", { className: "border-border-default border-b px-4 py-3", children: [_jsx("div", { className: "text-neutral-grey-100 text-sm font-medium", children: "Tickets needing attention" }), _jsx("div", { className: "text-neutral-grey-50 mt-0.5 text-xs", children: attentionTickets.length === attentionTotal
                                    ? `${attentionTotal} ticket${attentionTotal === 1 ? "" : "s"}`
                                    : `${attentionTickets.length} listed of ${attentionTotal} attention items` })] }), attentionTickets.length > 0 ? (_jsx("ul", { className: "max-h-80 overflow-y-auto p-2", "data-testid": "taskboard-attention-ticket-list", children: attentionTickets.map((ticket) => {
                            const ticketContent = (_jsx(_Fragment, { children: _jsxs("div", { className: "flex items-start justify-between gap-3", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: "text-neutral-grey-100 line-clamp-2 text-sm font-medium", children: ticket.title }), _jsxs("div", { className: "text-neutral-grey-50 mt-1 flex flex-wrap items-center gap-x-2 gap-y-1 text-xs", children: [_jsx("span", { children: ticket.taskReference }), _jsx("span", { children: ticket.projectTitle }), _jsx("span", { children: ticket.statusLabel })] })] }), _jsx("span", { className: "bg-feedback-orange-light text-feedback-orange shrink-0 rounded-full px-2 py-0.5 text-[10px] font-semibold", children: getAttentionLabel(ticket.reason) })] }) }));
                            return (_jsx("li", { children: onSelectTicket ? (_jsx("button", { type: "button", className: "hover:bg-neutral-grey-5 focus-visible:ring-component-suggestions block w-full rounded-md px-2.5 py-2 text-left outline-none focus-visible:ring-2", onClick: () => {
                                        onSelectTicket(ticket);
                                        setOpen(false);
                                    }, "data-testid": `taskboard-attention-ticket-${ticket.taskId}`, children: ticketContent })) : (_jsx("div", { className: "rounded-md px-2.5 py-2", children: ticketContent })) }, `${ticket.projectId}:${ticket.taskId}`));
                        }) })) : (_jsx("div", { className: "text-neutral-grey-50 px-4 py-5 text-sm", children: detailsLoading
                            ? "Ticket details are loading."
                            : "No ticket details are available for these attention items yet." }))] })] }));
}
export function TaskStateProgressBar(props) {
    const { counts, compact = false } = props;
    const total = counts.total;
    return (_jsx("div", { className: `${compact ? "h-1.5" : "h-2"} bg-neutral-grey-5 w-full overflow-hidden rounded-full`, children: total > 0 ? (_jsx("div", { className: "flex h-full w-full", children: STATE_STOPS.map((stop) => {
                const value = counts[stop.key];
                const widthPct = (value / total) * 100;
                return (_jsx("div", { className: stop.segmentClassName, style: { width: `${widthPct}%` }, title: `${stop.label}: ${value}` }, stop.key));
            }) })) : null }));
}
export function ProjectDashboard(props) {
    const { selectedProjectTitle, selectedProjectDescription, subprojects, parentProjectId, parentProjectTitle, onSelectProject, canCreateTask = false, onCreateTask, showCreateTaskButton = true, showSubprojectTaskVisibilityHint = false, } = props;
    const shouldShowSubprojectTaskVisibilityHint = showSubprojectTaskVisibilityHint && subprojects.length > 0;
    return (_jsxs("div", { "data-testid": "taskboard-project-dashboard", children: [parentProjectId && parentProjectTitle && onSelectProject && (_jsx("div", { className: "mb-3", children: _jsxs("button", { type: "button", className: "text-neutral-grey-50 hover:text-neutral-grey-100 inline-flex items-center gap-1.5 text-sm", onClick: () => onSelectProject(parentProjectId), "data-testid": "taskboard-parent-project-button", children: [_jsx(ChevronLeft, { className: "h-4 w-4", strokeWidth: 1.5 }), _jsxs("span", { children: ["Back to ", parentProjectTitle] })] }) })), _jsxs("div", { className: "flex flex-col gap-5 lg:flex-row lg:items-start lg:justify-between", children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsx(PageHeader, { title: selectedProjectTitle, description: selectedProjectDescription?.trim() || undefined, variant: "workspace" }), shouldShowSubprojectTaskVisibilityHint ? (_jsxs("div", { className: "border-feedback-blue bg-feedback-blue-light/40 text-feedback-blue mt-3 flex max-w-3xl items-start gap-2 rounded-md border px-3 py-2 text-xs leading-5", "data-testid": "taskboard-subproject-task-scope-hint", children: [_jsx(Info, { className: "mt-0.5 h-3.5 w-3.5 shrink-0", strokeWidth: 1.5 }), _jsx("span", { children: "Subproject tasks are not shown in this view. Select a subproject in the projects list to view its tasks." })] })) : null] }), showCreateTaskButton ? (_jsx("div", { className: "flex shrink-0 flex-wrap items-center gap-3", children: _jsxs(Button, { onClick: () => onCreateTask?.(), disabled: !canCreateTask || !onCreateTask, "data-testid": "taskboard-create-task-button", children: [_jsx("span", { children: "Create new task" }), _jsx(Plus, { className: "h-4 w-4", strokeWidth: 1.5 })] }) })) : null] })] }));
}
export function ProjectKpisPanel(props) {
    const { selectedProjectCostUsed = 0, selectedProjectCostLimit = null, selectedProjectTaskCounts, selectedProjectAttention, subprojects, taskCountsByProjectId, attentionTaskGroups = [], attentionDetailsLoading = false, onSelectAttentionTask, } = props;
    const normalizedCostUsed = Number.isFinite(selectedProjectCostUsed)
        ? Math.max(0, selectedProjectCostUsed)
        : 0;
    const effectiveCostLimit = typeof selectedProjectCostLimit === "number" && selectedProjectCostLimit > 0
        ? selectedProjectCostLimit
        : DEFAULT_COST_LIMIT;
    const budgetPercent = effectiveCostLimit > 0
        ? Math.max(0, (normalizedCostUsed / effectiveCostLimit) * 100)
        : 0;
    const remainingBudget = effectiveCostLimit - normalizedCostUsed;
    const aggregatedCounts = aggregateTaskCounts(selectedProjectTaskCounts, subprojects, taskCountsByProjectId);
    const completionPercent = aggregatedCounts.total > 0
        ? (aggregatedCounts.done / aggregatedCounts.total) * 100
        : 0;
    const openTasks = Math.max(0, aggregatedCounts.total - aggregatedCounts.done);
    const attention = aggregateAttention(selectedProjectAttention, subprojects);
    const attentionTotal = attention.total ||
        attention.blocked +
            attention.approval +
            attention.input +
            attention.failed +
            attention.budget +
            (attention.capacity ?? 0);
    const attentionTickets = buildAttentionTickets(attentionTaskGroups);
    const budgetDetail = remainingBudget >= 0
        ? `${formatCurrency(remainingBudget)} remaining of ${formatCurrency(effectiveCostLimit)}`
        : `${formatCurrency(Math.abs(remainingBudget))} over ${formatCurrency(effectiveCostLimit)}`;
    return (_jsxs("div", { className: "min-h-0 space-y-4", "data-testid": "taskboard-project-kpis-panel", children: [_jsxs("div", { className: "grid gap-3 md:grid-cols-2 xl:grid-cols-4", children: [_jsx(KpiTile, { icon: _jsx(CircleDollarSign, { className: "size-4", strokeWidth: 1.5 }), label: "Budget used", value: formatCurrency(normalizedCostUsed), detail: `${formatPercent(budgetPercent)} of budget. ${budgetDetail}`, testId: "taskboard-kpi-budget" }), _jsx(KpiTile, { icon: _jsx(CheckCircle2, { className: "size-4", strokeWidth: 1.5 }), label: "Completion", value: formatPercent(completionPercent), detail: `${aggregatedCounts.done} of ${aggregatedCounts.total} tasks done`, testId: "taskboard-kpi-completion" }), _jsx(KpiTile, { icon: _jsx(Timer, { className: "size-4", strokeWidth: 1.5 }), label: "Open tasks", value: openTasks, detail: `${aggregatedCounts.inProgress} in progress, ${aggregatedCounts.waiting} waiting`, testId: "taskboard-kpi-open-tasks" }), _jsx(KpiTile, { icon: _jsx(FolderTree, { className: "size-4", strokeWidth: 1.5 }), label: "Subprojects", value: subprojects.length, detail: subprojects.length === 1
                            ? "1 direct subproject"
                            : `${subprojects.length} direct subprojects`, testId: "taskboard-kpi-subprojects" })] }), _jsxs("div", { className: "grid gap-4 xl:grid-cols-[minmax(0,1.35fr)_minmax(280px,0.65fr)]", children: [_jsxs("section", { className: "border-border-default rounded-md border bg-white p-4", children: [_jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "bg-neutral-grey-5 text-neutral-grey-50 flex size-8 items-center justify-center rounded-md", children: _jsx(ClipboardList, { className: "size-4", strokeWidth: 1.5 }) }), _jsxs("div", { children: [_jsx("h2", { className: "text-neutral-grey-100 text-base font-medium", children: "Task status" }), _jsxs("p", { className: "text-neutral-grey-50 text-xs", children: [aggregatedCounts.total, " total tasks including direct subprojects"] })] })] }), _jsx("div", { className: "text-neutral-grey-100 text-xl font-medium", children: formatPercent(completionPercent) })] }), _jsx("div", { className: "mt-4", children: _jsx(TaskStateProgressBar, { counts: aggregatedCounts }) }), _jsx("div", { className: "mt-4 grid gap-2 md:grid-cols-2", children: STATE_STOPS.map((stop) => {
                                    const value = aggregatedCounts[stop.key];
                                    const percent = aggregatedCounts.total > 0
                                        ? (value / aggregatedCounts.total) * 100
                                        : 0;
                                    return (_jsxs("div", { className: "bg-neutral-grey-5/60 flex items-center justify-between gap-3 rounded-md px-3 py-2 text-sm", children: [_jsxs("span", { className: "flex min-w-0 items-center gap-2", children: [_jsx("span", { className: `inline-block size-2 rounded-full ${stop.swatchClassName}` }), _jsx("span", { className: "text-neutral-grey-100 truncate", children: stop.label })] }), _jsxs("span", { className: "text-neutral-grey-50 shrink-0 text-xs tabular-nums", children: [value, " / ", formatPercent(percent)] })] }, stop.key));
                                }) })] }), _jsxs("section", { className: "border-border-default rounded-md border bg-white p-4", children: [_jsx(AttentionSummaryHeader, { attentionTotal: attentionTotal, attentionTickets: attentionTickets, detailsLoading: attentionDetailsLoading, onSelectTicket: onSelectAttentionTask
                                    ? (ticket) => onSelectAttentionTask(ticket.taskId)
                                    : undefined }), _jsx("div", { className: "mt-4 space-y-2", children: ATTENTION_STOPS.map((stop) => {
                                    const value = attention[stop.key] ?? 0;
                                    return (_jsxs("div", { className: "bg-neutral-grey-5/60 flex items-center justify-between gap-3 rounded-md px-3 py-2 text-sm", children: [_jsxs("span", { className: "flex min-w-0 items-center gap-2", children: [_jsx("span", { className: `inline-block size-2 rounded-full ${stop.swatchClassName}` }), _jsx("span", { className: "text-neutral-grey-100 truncate", children: stop.label })] }), _jsx("span", { className: "text-neutral-grey-50 shrink-0 text-xs tabular-nums", children: value })] }, stop.key));
                                }) })] })] })] }));
}
//# sourceMappingURL=ProjectDashboard.js.map