import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import React, { useState, useEffect, useRef } from "react";
import { Box, Text, Static, useInput, useStdout } from "ink";
import { useTheme } from "../theme/theme.js";
import { Markdown } from "./Markdown.js";
import { useTerminalSize } from "../hooks/useTerminalSize.js";
import { visualWidth } from "../utils/table-text.js";
import { readdir, readFile, unlink } from "node:fs/promises";
import { join } from "node:path";
// ── Plan loading ─────────────────────────────────────────
async function loadPlanEntries(cwd) {
    const plansDir = join(cwd, ".gg", "plans");
    let files;
    try {
        files = await readdir(plansDir);
    }
    catch {
        return [];
    }
    const entries = [];
    for (const file of files) {
        if (!file.endsWith(".md"))
            continue;
        const filePath = join(plansDir, file);
        try {
            const { mtimeMs } = await import("node:fs").then((fs) => fs.statSync(filePath));
            entries.push({
                name: file.replace(/\.md$/, ""),
                path: filePath,
                modifiedMs: mtimeMs,
            });
        }
        catch {
            entries.push({ name: file.replace(/\.md$/, ""), path: filePath, modifiedMs: 0 });
        }
    }
    // Sort newest first
    entries.sort((a, b) => b.modifiedMs - a.modifiedMs);
    return entries;
}
// ── Banner ───────────────────────────────────────────────
const PLAN_LOGO = [
    " \u2584\u2580\u2580\u2580 \u2584\u2580\u2580\u2580",
    " \u2588 \u2580\u2588 \u2588 \u2580\u2588",
    " \u2580\u2584\u2584\u2580 \u2580\u2584\u2584\u2580",
];
const YOUR_PLAN_LOGO = [
    "▗▖  ▗▖▗▄▖ ▗▖ ▗▖▗▄▄▖     ▗▄▄▖ ▗▖    ▗▄▖ ▗▖  ▗▖",
    " ▝▚▞▘▐▌ ▐▌▐▌ ▐▌▐▌ ▐▌    ▐▌ ▐▌▐▌   ▐▌ ▐▌▐▛▚▖▐▌",
    "  ▐▌ ▐▌ ▐▌▐▌ ▐▌▐▛▀▚▖    ▐▛▀▘ ▐▌   ▐▛▀▜▌▐▌ ▝▜▌",
    "  ▐▌ ▝▚▄▞▘▝▚▄▞▘▐▌ ▐▌    ▐▌   ▐▙▄▄▖▐▌ ▐▌▐▌  ▐▌",
];
const AMBER_GRADIENT = [
    "#f59e0b",
    "#fbbf24",
    "#f59e0b",
    "#d97706",
    "#f59e0b",
    "#fbbf24",
    "#d97706",
];
const GAP = "   ";
const LOGO_VISUAL_WIDTH = visualWidth(PLAN_LOGO[0]);
const SIDE_BY_SIDE_MIN = LOGO_VISUAL_WIDTH + GAP.length + 20;
/**
 * Render logo text with an amber gradient, batching consecutive same-color
 * characters into single <Text> elements to reduce ANSI escape overhead.
 */
function PlanGradientText({ text }) {
    const spans = [];
    let colorIdx = 0;
    let currentColor = "";
    let currentChars = "";
    const flush = () => {
        if (currentChars) {
            spans.push(_jsx(Text, { color: currentColor, children: currentChars }, spans.length));
            currentChars = "";
        }
    };
    for (let i = 0; i < text.length; i++) {
        const ch = text[i];
        if (ch === " ") {
            // Spaces don't need color — batch them with the current run
            currentChars += ch;
        }
        else {
            const color = AMBER_GRADIENT[colorIdx % AMBER_GRADIENT.length];
            if (color !== currentColor) {
                flush();
                currentColor = color;
            }
            currentChars += ch;
            colorIdx++;
        }
    }
    flush();
    return _jsx(Text, { children: spans });
}
// ── Prefix width — matches AssistantMessage / StreamingArea ──
const PREFIX_WIDTH = 2;
export function PlanActionBar({ planName, confirmDelete, rejectMode, rejectFeedback, }) {
    const theme = useTheme();
    return (_jsxs(Box, { flexDirection: "column", paddingLeft: 1, children: [confirmDelete && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: theme.error, children: ["  Delete ", _jsx(Text, { bold: true, children: planName }), "? (y/N)"] }) })), rejectMode ? (_jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { color: theme.planPrimary, children: "Feedback (Enter to submit, Esc to cancel):" }), _jsx(Box, { children: _jsxs(Text, { color: theme.text, children: ["> ", rejectFeedback, "▍"] }) })] })) : (_jsxs(Box, { marginTop: 1, flexDirection: "row", children: [_jsx(Box, { width: 2, flexShrink: 0, children: _jsx(Text, { color: theme.planPrimary, children: "◇ " }) }), _jsxs(Text, { color: theme.textDim, children: [_jsx(Text, { color: theme.success, children: "a" }), " approve · ", _jsx(Text, { color: theme.error, children: "r" }), " reject · ", _jsx(Text, { color: theme.planPrimary, children: "d" }), " delete · ", _jsx(Text, { color: theme.planPrimary, children: "q" }), " back · ", _jsx(Text, { color: theme.planPrimary, children: "ESC" }), " close"] })] }))] }));
}
export function PlanOverlay({ cwd, onClose, autoExpandNewest, onApprove, onReject, onDeletePlan, }) {
    const theme = useTheme();
    const { stdout } = useStdout();
    const { columns } = useTerminalSize();
    // Pre-compute the width available for Markdown — same as AssistantMessage.
    // Prefix (2) = 2 chars overhead.
    const markdownWidth = Math.max(40, columns - PREFIX_WIDTH);
    const [plans, setPlans] = useState([]);
    const [selectedIndex, setSelectedIndex] = useState(0);
    const [loaded, setLoaded] = useState(false);
    // Expanded view state
    const [expandedPlan, setExpandedPlan] = useState(null);
    const [staticItems, setStaticItems] = useState([]);
    // Action state
    const [confirmDelete, setConfirmDelete] = useState(false);
    const [rejectMode, setRejectMode] = useState(false);
    const [rejectFeedback, setRejectFeedback] = useState("");
    const autoExpandedRef = useRef(false);
    const nextIdRef = useRef(0);
    const getId = () => String(nextIdRef.current++);
    // Load plans on mount
    useEffect(() => {
        void loadPlanEntries(cwd).then((p) => {
            setPlans(p);
            setLoaded(true);
        });
    }, [cwd]);
    // Auto-expand newest plan on first load
    useEffect(() => {
        if (autoExpandNewest && loaded && plans.length > 0 && !autoExpandedRef.current) {
            autoExpandedRef.current = true;
            expandPlan(plans[0]);
        }
    }, [autoExpandNewest, loaded, plans]);
    // Clamp index
    useEffect(() => {
        if (plans.length === 0) {
            setSelectedIndex(0);
        }
        else if (selectedIndex >= plans.length) {
            setSelectedIndex(plans.length - 1);
        }
    }, [plans.length, selectedIndex]);
    function expandPlan(plan) {
        void readFile(plan.path, "utf-8")
            .then((content) => {
            setExpandedPlan(plan);
            setStaticItems([
                { kind: "banner", id: getId() },
                { kind: "plan_header", name: plan.name, id: getId() },
                { kind: "plan_content", content, markdownWidth, id: getId() },
            ]);
        })
            .catch(() => {
            setExpandedPlan(plan);
            setStaticItems([
                { kind: "banner", id: getId() },
                { kind: "plan_header", name: plan.name, id: getId() },
                { kind: "plan_content", content: "(could not read plan)", markdownWidth, id: getId() },
            ]);
        });
    }
    function collapsePlan() {
        // The expanded view renders into <Static>, which flushes to terminal
        // scrollback. Unmounting alone leaves that content above the list view;
        // clear the terminal so the list redraws clean.
        stdout?.write("\x1b[2J\x1b[3J\x1b[H");
        setExpandedPlan(null);
        setStaticItems([]);
        setRejectMode(false);
        setRejectFeedback("");
        autoExpandedRef.current = true;
    }
    useInput((input, key) => {
        // Reject feedback input mode
        if (rejectMode) {
            if (key.return) {
                if (expandedPlan) {
                    onReject?.(expandedPlan.path, rejectFeedback || "Please revise the plan.");
                }
                setRejectMode(false);
                setRejectFeedback("");
                return;
            }
            if (key.escape) {
                setRejectMode(false);
                setRejectFeedback("");
                return;
            }
            if (key.backspace || key.delete) {
                setRejectFeedback((prev) => prev.slice(0, -1));
                return;
            }
            if (input && !key.ctrl && !key.meta) {
                setRejectFeedback((prev) => prev + input);
            }
            return;
        }
        // Confirm delete mode
        if (confirmDelete) {
            if (input === "y" || input === "Y") {
                const plan = expandedPlan ?? plans[selectedIndex];
                if (plan) {
                    void unlink(plan.path).catch(() => { });
                    onDeletePlan?.(plan.path);
                    setPlans((prev) => prev.filter((p) => p.path !== plan.path));
                    if (expandedPlan)
                        collapsePlan();
                }
                setConfirmDelete(false);
                return;
            }
            setConfirmDelete(false);
            return;
        }
        // Close overlay
        if (key.escape) {
            if (expandedPlan) {
                collapsePlan();
            }
            else {
                onClose();
            }
            return;
        }
        // ── Expanded view actions ──
        if (expandedPlan) {
            if (input === "a") {
                onApprove?.(expandedPlan.path);
                return;
            }
            if (input === "r") {
                setRejectMode(true);
                setRejectFeedback("");
                return;
            }
            if (input === "d") {
                setConfirmDelete(true);
                return;
            }
            // q or Enter → back to list
            if (input === "q" || key.return) {
                collapsePlan();
                return;
            }
            return;
        }
        // ── List view navigation ──
        if (key.upArrow || input === "k") {
            setSelectedIndex((i) => Math.max(0, i - 1));
            return;
        }
        if (key.downArrow || input === "j") {
            setSelectedIndex((i) => Math.min(plans.length - 1, i + 1));
            return;
        }
        // Expand selected plan
        if (key.return || input === " ") {
            const plan = plans[selectedIndex];
            if (plan)
                expandPlan(plan);
            return;
        }
        // Delete plan
        if (input === "d") {
            const plan = plans[selectedIndex];
            if (plan)
                setConfirmDelete(true);
            return;
        }
    });
    function renderYourPlanBanner() {
        return (_jsx(Box, { flexDirection: "column", marginBottom: 1, paddingLeft: 1, width: columns, children: YOUR_PLAN_LOGO.map((line, index) => (_jsx(PlanGradientText, { text: line }, index))) }));
    }
    // ── Shared banner renderer ──
    function renderBanner(subtitle) {
        return columns < SIDE_BY_SIDE_MIN ? (_jsxs(Box, { flexDirection: "column", marginTop: 1, marginBottom: 1, width: columns, children: [_jsx(PlanGradientText, { text: PLAN_LOGO[0] }), _jsx(PlanGradientText, { text: PLAN_LOGO[1] }), _jsx(PlanGradientText, { text: PLAN_LOGO[2] }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: theme.planPrimary, bold: true, children: "Plan Pane" }) }), subtitle && _jsx(Text, { color: theme.textDim, children: subtitle })] })) : (_jsxs(Box, { flexDirection: "column", marginTop: 1, marginBottom: 1, width: columns, children: [_jsxs(Box, { children: [_jsx(PlanGradientText, { text: PLAN_LOGO[0] }), _jsx(Text, { children: GAP }), _jsx(Text, { color: theme.planPrimary, bold: true, children: "Plan Pane" })] }), _jsxs(Box, { children: [_jsx(PlanGradientText, { text: PLAN_LOGO[1] }), subtitle && (_jsxs(_Fragment, { children: [_jsx(Text, { children: GAP }), _jsx(Text, { color: theme.textDim, children: subtitle })] }))] }), _jsx(Box, { children: _jsx(PlanGradientText, { text: PLAN_LOGO[2] }) })] }));
    }
    const expandedActionArea = (_jsx(PlanActionBar, { planName: expandedPlan?.name, confirmDelete: confirmDelete, rejectMode: rejectMode, rejectFeedback: rejectFeedback }));
    // ── Expanded view (Static pushes content into terminal scrollback for native scroll) ──
    if (expandedPlan) {
        return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Static, { items: staticItems, children: (item) => {
                        if (item.kind === "banner") {
                            return _jsx(React.Fragment, { children: renderYourPlanBanner() }, item.id);
                        }
                        if (item.kind === "plan_header") {
                            return (_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { color: theme.planPrimary, bold: true, children: ["◆ ", item.name] }) }, item.id));
                        }
                        if (item.kind === "plan_content") {
                            return (_jsxs(Box, { flexDirection: "row", marginTop: 1, paddingRight: 1, children: [_jsx(Box, { width: PREFIX_WIDTH, flexShrink: 0, children: _jsx(Text, { color: theme.planPrimary, children: "◇ " }) }), _jsx(Box, { flexDirection: "column", flexGrow: 1, width: item.markdownWidth, children: _jsx(Markdown, { width: item.markdownWidth, children: item.content }) })] }, item.id));
                        }
                        return null;
                    } }), expandedActionArea] }));
    }
    // ── List view ──
    const maxVisible = 15;
    const startIdx = Math.max(0, selectedIndex - maxVisible + 1);
    const visiblePlans = plans.slice(startIdx, startIdx + maxVisible);
    return (_jsxs(Box, { flexDirection: "column", children: [renderBanner(`${plans.length} plan${plans.length !== 1 ? "s" : ""} in .gg/plans/`), loaded && plans.length === 0 && (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { color: theme.textDim, children: ["  No plans found. Plans are written to ", _jsx(Text, { color: theme.planPrimary, children: ".gg/plans/" })] }), _jsx(Text, { color: theme.textDim, children: "  No pending plans are available for review." })] })), visiblePlans.map((plan, vi) => {
                const realIdx = startIdx + vi;
                const selected = realIdx === selectedIndex;
                const prefix = selected ? "❯ " : "  ";
                const date = new Date(plan.modifiedMs);
                const timeStr = plan.modifiedMs > 0
                    ? `${date.getMonth() + 1}/${date.getDate()} ${date.getHours()}:${String(date.getMinutes()).padStart(2, "0")}`
                    : "";
                return (_jsxs(Text, { color: selected ? theme.planPrimary : theme.text, bold: selected, children: [prefix, _jsx(Text, { color: selected ? theme.planPrimary : "#e5e7eb", children: plan.name }), timeStr && (_jsxs(Text, { color: theme.textDim, dimColor: !selected, children: [" ", timeStr] }))] }, plan.path));
            }), confirmDelete && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: theme.error, children: ["  Delete ", _jsx(Text, { bold: true, children: plans[selectedIndex]?.name }), "? (y/N)"] }) })), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: theme.textDim, children: [_jsx(Text, { color: theme.planPrimary, children: "\u2191\u2193" }), " move · ", _jsx(Text, { color: theme.planPrimary, children: "Enter" }), " view · ", _jsx(Text, { color: theme.planPrimary, children: "d" }), " delete · ", _jsx(Text, { color: theme.planPrimary, children: "ESC" }), " close"] }) })] }));
}
//# sourceMappingURL=PlanOverlay.js.map