import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { Box, Text } from "ink";
import { useTerminalSize } from "../hooks/useTerminalSize.js";
import { Pane } from "./design/Pane.js";
import { SelectList } from "./design/SelectList.js";
import { StatusBadge } from "./design/StatusBadge.js";
import { Tabs } from "./design/Tabs.js";
import { truncateCells } from "./design/textLayout.js";
const CHECKPOINT_FILE_PREVIEW_LIMIT = 12;
const DIFF_PREVIEW_LIMIT = 10;
export function WorkspacePanel(props) {
    const { columns } = useTerminalSize();
    const width = Math.max(58, Math.min(116, columns - 4));
    return (_jsx(Box, { flexDirection: "column", marginBottom: 1, children: _jsxs(Pane, { width: width, title: "workspace", tone: "brand", paddingX: 1, children: [_jsxs(Box, { flexDirection: "row", justifyContent: "space-between", children: [_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { bold: true, color: "cyan", children: props.model.title }), _jsx(Text, { color: "gray", children: truncateCells(props.model.subtitle, Math.max(24, width - 20)) })] }), _jsx(StatusBadge, { label: props.model.badge, tone: props.model.badgeTone })] }), _jsx(Box, { marginTop: 1, children: _jsx(Tabs, { selectedId: "records", title: "view", tabs: workspacePanelTabs(props.model), width: width }) }), _jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { color: "gray", children: "records" }), props.model.rows.length === 0 ? (_jsx(Text, { color: "gray", children: "No workspace records" })) : (_jsx(SelectList, { options: workspacePanelRowOptions(props.model), selectedIndex: 0, visibleCount: 8, width: width }))] }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "gray", children: "commands" }) }), _jsx(SelectList, { options: workspacePanelCommandOptions(props.model), selectedIndex: 0, visibleCount: 4, width: width }), _jsx(Text, { color: "gray", children: truncateCells(props.model.footer, Math.max(24, width - 4)) })] }) }));
}
export function checkpointListPanelModel(checkpoints, checkpointDir) {
    return {
        title: "Checkpoints",
        subtitle: checkpointDir,
        badge: checkpoints.length ? `${checkpoints.length}` : "none",
        badgeTone: checkpoints.length ? "brand" : "muted",
        rows: checkpoints.map((checkpoint) => ({
            key: checkpoint.id,
            label: checkpoint.truncated ? "partial" : "complete",
            value: checkpoint.id,
            tone: checkpoint.truncated ? "warning" : "success",
            note: `${checkpoint.fileCount} files | ${checkpoint.totalBytes} bytes | ${formatTime(checkpoint.createdAtMs)} | ${checkpoint.label}`,
        })),
        footer: "/rewind create [label] | /rewind show <id> | /rewind restore <id>",
    };
}
export function checkpointCreatedPanelModel(checkpoint) {
    return checkpointDetailPanelModel(checkpoint, "Checkpoint created");
}
export function checkpointDetailPanelModel(checkpoint, title = "Checkpoint detail") {
    const fileRows = checkpoint.files.slice(0, CHECKPOINT_FILE_PREVIEW_LIMIT).map((file) => ({
        key: file.path,
        label: "file",
        value: file.path,
        tone: "muted",
        note: `${file.size} bytes | ${file.sha256.slice(0, 12)}`,
    }));
    const clipped = checkpoint.files.length > CHECKPOINT_FILE_PREVIEW_LIMIT
        ? [{
                key: "clipped",
                label: "more",
                value: `${checkpoint.files.length - CHECKPOINT_FILE_PREVIEW_LIMIT} more files`,
                tone: "warning",
            }]
        : [];
    return {
        title,
        subtitle: checkpoint.label,
        badge: checkpoint.truncated ? "partial" : "complete",
        badgeTone: checkpoint.truncated ? "warning" : "success",
        rows: [
            {
                key: "summary",
                label: "summary",
                value: checkpoint.id,
                tone: "brand",
                note: `${checkpoint.fileCount} files | ${checkpoint.totalBytes} bytes | ${formatTime(checkpoint.createdAtMs)}`,
            },
            ...fileRows,
            ...clipped,
        ],
        footer: "/rewind diff <id> | /rewind restore <id> [--delete-new]",
    };
}
export function checkpointDiffPanelModel(id, diff) {
    const lines = diff.diff
        .split(/\r?\n/)
        .filter((line) => line.trim())
        .slice(0, DIFF_PREVIEW_LIMIT);
    return {
        title: "Checkpoint diff",
        subtitle: id,
        badge: diff.changed ? "changed" : "clean",
        badgeTone: diff.changed ? "warning" : "success",
        rows: [
            {
                key: "summary",
                label: "summary",
                value: `changed=${diff.changed} added=${diff.added} removed=${diff.removed}`,
                tone: diff.changed ? "warning" : "success",
            },
            ...lines.map((line, index) => ({
                key: `line-${index}`,
                label: diffLineLabel(line),
                value: line,
                tone: diffLineTone(line),
            })),
        ],
        footer: "/diff git | /rewind restore <id> | /export status",
    };
}
export function checkpointRestorePanelModel(id, result, deleteNew) {
    return {
        title: "Checkpoint restore",
        subtitle: id,
        badge: "restored",
        badgeTone: result.restored || result.deleted ? "success" : "brand",
        rows: [
            { key: "restored", label: "restored", value: String(result.restored), tone: "success" },
            { key: "deleted", label: "deleted", value: String(result.deleted), tone: deleteNew ? "warning" : "muted" },
            { key: "skipped", label: "skipped", value: String(result.skipped), tone: "muted" },
        ],
        footer: "/diff git | /rewind list | /validation",
    };
}
export function checkpointPathPanelModel(checkpointDir) {
    return {
        title: "Checkpoint path",
        subtitle: checkpointDir,
        badge: "path",
        badgeTone: "brand",
        rows: [{ key: "path", label: "path", value: checkpointDir, tone: "brand" }],
        footer: "/rewind list | /rewind create [label]",
    };
}
export function attachListPanelModel(runs, currentRunId) {
    return {
        title: "Attachable runs",
        subtitle: currentRunId ? "current run attached" : "No attached run",
        badge: runs.length ? `${runs.length}` : "none",
        badgeTone: runs.length ? "brand" : "muted",
        rows: runs.map((run, index) => runRow(run, currentRunId === run.id ? "current" : run.status, runListLabel(index))),
        footer: "/attach latest | /attach current | /attach clear",
    };
}
export function attachCurrentPanelModel(snapshot) {
    if (!snapshot.runId) {
        return {
            title: "Attached run",
            subtitle: "No attached run",
            badge: "none",
            badgeTone: "muted",
            rows: [],
            footer: "/attach list | /attach latest",
        };
    }
    if (!snapshot.run) {
        return {
            title: "Attached run",
            subtitle: "Attached run record is missing",
            badge: "missing",
            badgeTone: "warning",
            rows: [{ key: "missing", label: "missing", value: "missing attached run", tone: "warning" }],
            footer: "/attach clear | /runs",
        };
    }
    return {
        title: "Attached run",
        subtitle: "current run",
        badge: snapshot.run.status,
        badgeTone: runTone(snapshot.run.status),
        rows: [runRow(snapshot.run, "current", "current run")],
        footer: "/tasks attached | /queue attached | /trace attached",
    };
}
export function attachActionPanelModel(run, action) {
    return {
        title: action === "attached" ? "Run attached" : "Attached run cleared",
        subtitle: action === "attached" ? "current run" : "No attached run",
        badge: action,
        badgeTone: action === "attached" ? "success" : "muted",
        rows: [runRow(run, action, action === "attached" ? "current run" : "previous run")],
        footer: action === "attached" ? "/tasks attached | /trace attached | /attach clear" : "/attach list | /runs",
    };
}
export function attachClearedPanelModel(runId) {
    return {
        title: "Attached run cleared",
        subtitle: runId ? "Previous attached run cleared" : "No previous run",
        badge: "cleared",
        badgeTone: "muted",
        rows: runId ? [{ key: "cleared", label: "cleared", value: "previous attached run", tone: "muted" }] : [],
        footer: "/attach list | /attach latest",
    };
}
export function workspacePanelTabs(model) {
    return [
        { id: "records", title: "records", count: model.rows.length, tone: model.rows.length > 0 ? "brand" : "muted" },
        { id: "commands", title: "commands", count: workspacePanelCommandOptions(model).length, tone: "muted" },
    ];
}
export function workspacePanelRowOptions(model) {
    return model.rows.map((row, index) => ({
        id: row.key,
        label: row.label,
        detail: row.value,
        description: row.note,
        selected: index === 0,
        tone: row.tone,
    }));
}
export function workspacePanelCommandOptions(model) {
    const lowerTitle = model.title.toLowerCase();
    if (lowerTitle.includes("checkpoint diff")) {
        return [
            commandOption("restore", "/rewind restore <id>", "restore files from this checkpoint", "warning"),
            commandOption("diff", "/diff git", "compare current workspace state", "brand"),
            commandOption("list", "/rewind list", "return to checkpoint list", "muted"),
        ];
    }
    if (lowerTitle.includes("checkpoint restore")) {
        return [
            commandOption("diff", "/diff git", "inspect workspace after restore", "brand"),
            commandOption("list", "/rewind list", "return to checkpoint list", "success"),
            commandOption("validation", "/validation", "check artifact validation gates", "muted"),
        ];
    }
    if (lowerTitle.includes("checkpoint")) {
        return [
            commandOption("show", "/rewind show <id>", "inspect checkpoint file snapshot", "brand"),
            commandOption("diff", "/rewind diff <id>", "preview changes before restore", "success"),
            commandOption("restore", "/rewind restore <id>", "restore tracked text files", "warning"),
            commandOption("create", "/rewind create [label]", "capture a new checkpoint", "muted"),
        ];
    }
    if (lowerTitle.includes("attachable")) {
        return [
            commandOption("latest", "/attach latest", "focus the most recent unfinished run", "brand"),
            commandOption("current", "/attach current", "show the attached run", "success"),
            commandOption("clear", "/attach clear", "clear attached run focus", "muted"),
        ];
    }
    if (lowerTitle.includes("attached") || lowerTitle.includes("run attached")) {
        return [
            commandOption("tasks", "/tasks attached", "show attached run tasks", "brand"),
            commandOption("queue", "/queue attached", "show runnable task queue", "success"),
            commandOption("trace", "/trace attached", "inspect attached run events", "warning"),
            commandOption("clear", "/attach clear", "clear attached focus", "muted"),
        ];
    }
    return [
        commandOption("rewind", "/rewind list", "browse workspace checkpoints", "brand"),
        commandOption("attach", "/attach list", "browse attachable runs", "success"),
    ];
}
function commandOption(id, detail, description, tone) {
    return {
        id,
        label: id,
        detail,
        description,
        tone,
    };
}
function runRow(run, label, value) {
    return {
        key: run.id,
        label,
        value,
        tone: label === "current" || label === "attached" ? "success" : runTone(run.status),
        note: `${run.status} | actions=${run.actionCount} artifacts=${run.artifactCount} events=${run.eventCount} | ${run.message || "(no message)"}`,
    };
}
function runListLabel(index) {
    return `run ${index + 1}`;
}
function runTone(status) {
    if (status === "succeeded")
        return "success";
    if (status === "failed" || status === "cancelled")
        return "error";
    if (status === "running" || status === "paused")
        return "warning";
    return "muted";
}
function formatTime(value) {
    if (!Number.isFinite(value) || value <= 0)
        return "";
    return new Date(value).toISOString().replace("T", " ").replace(/\.\d+Z$/, "Z");
}
function diffLineLabel(line) {
    if (line.startsWith("+"))
        return "add";
    if (line.startsWith("-"))
        return "remove";
    if (line.startsWith("@@"))
        return "hunk";
    if (line.startsWith("file "))
        return "file";
    return "diff";
}
function diffLineTone(line) {
    if (line.startsWith("+"))
        return "success";
    if (line.startsWith("-"))
        return "error";
    if (line.startsWith("@@"))
        return "brand";
    if (line.startsWith("file "))
        return "warning";
    return "muted";
}
