import { Container, getKeybindings, Input, Spacer, Text } from "@earendil-works/pi-tui";
import { KeybindingsManager } from "../../../core/keybindings.js";
import { theme } from "../theme/theme.js";
import { DynamicBorder } from "./dynamic-border.js";
import { keyText } from "./keybinding-hints.js";
import { deleteSessionFile } from "./session-selector-delete.js";
import { SessionSelectorHeader } from "./session-selector-header.js";
import { SessionList } from "./session-selector-list.js";
/**
 * Component that renders a session selector
 */
export class SessionSelectorComponent extends Container {
    handleInput(data) {
        if (this.mode === "rename") {
            const kb = getKeybindings();
            if (kb.matches(data, "tui.select.cancel")) {
                this.exitRenameMode();
                return;
            }
            this.renameInput.handleInput(data);
            return;
        }
        this.sessionList.handleInput(data);
    }
    get focused() {
        return this._focused;
    }
    set focused(value) {
        this._focused = value;
        this.sessionList.focused = value;
        this.renameInput.focused = value;
        if (value && this.mode === "rename") {
            this.renameInput.focused = true;
        }
    }
    buildBaseLayout(content, options) {
        this.clear();
        this.addChild(new Spacer(1));
        this.addChild(new DynamicBorder((s) => theme.fg("accent", s)));
        this.addChild(new Spacer(1));
        if (options?.showHeader ?? true) {
            this.addChild(this.header);
            this.addChild(new Spacer(1));
        }
        this.addChild(content);
        this.addChild(new Spacer(1));
        this.addChild(new DynamicBorder((s) => theme.fg("accent", s)));
    }
    constructor(currentSessionsLoader, allSessionsLoader, onSelect, onCancel, onExit, requestRender, options, currentSessionFilePath) {
        super();
        this.canRename = true;
        this.scope = "current";
        this.sortMode = "threaded";
        this.nameFilter = "all";
        this.currentSessions = null;
        this.allSessions = null;
        this.currentLoading = false;
        this.allLoading = false;
        this.allLoadSeq = 0;
        this.mode = "list";
        this.renameInput = new Input();
        this.renameTargetPath = null;
        // Focusable implementation - propagate to sessionList for IME cursor positioning
        this._focused = false;
        this.keybindings = options?.keybindings ?? KeybindingsManager.create();
        this.currentSessionsLoader = currentSessionsLoader;
        this.allSessionsLoader = allSessionsLoader;
        this.onCancel = onCancel;
        this.requestRender = requestRender;
        this.header = new SessionSelectorHeader(this.scope, this.sortMode, this.nameFilter, this.requestRender);
        const renameSession = options?.renameSession;
        this.renameSession = renameSession;
        this.canRename = !!renameSession;
        this.header.setShowRenameHint(options?.showRenameHint ?? this.canRename);
        // Create session list (starts empty, will be populated after load)
        this.sessionList = new SessionList([], false, this.sortMode, this.nameFilter, this.keybindings, currentSessionFilePath);
        this.buildBaseLayout(this.sessionList);
        this.renameInput.onSubmit = (value) => {
            void this.confirmRename(value);
        };
        // Ensure header status timeouts are cleared when leaving the selector
        const clearStatusMessage = () => this.header.setStatusMessage(null);
        this.sessionList.onSelect = (sessionPath) => {
            clearStatusMessage();
            onSelect(sessionPath);
        };
        this.sessionList.onCancel = () => {
            clearStatusMessage();
            onCancel();
        };
        this.sessionList.onExit = () => {
            clearStatusMessage();
            onExit();
        };
        this.sessionList.onToggleScope = () => this.toggleScope();
        this.sessionList.onToggleSort = () => this.toggleSortMode();
        this.sessionList.onToggleNameFilter = () => this.toggleNameFilter();
        this.sessionList.onRenameSession = (sessionPath) => {
            if (!renameSession)
                return;
            if (this.scope === "current" && this.currentLoading)
                return;
            if (this.scope === "all" && this.allLoading)
                return;
            const sessions = this.scope === "all" ? (this.allSessions ?? []) : (this.currentSessions ?? []);
            const session = sessions.find((s) => s.path === sessionPath);
            this.enterRenameMode(sessionPath, session?.name);
        };
        // Sync list events to header
        this.sessionList.onTogglePath = (showPath) => {
            this.header.setShowPath(showPath);
            this.requestRender();
        };
        this.sessionList.onDeleteConfirmationChange = (path) => {
            this.header.setConfirmingDeletePath(path);
            this.requestRender();
        };
        this.sessionList.onError = (msg) => {
            this.header.setStatusMessage({ type: "error", message: msg }, 3000);
            this.requestRender();
        };
        // Handle session deletion
        this.sessionList.onDeleteSession = async (sessionPath) => {
            const result = await deleteSessionFile(sessionPath);
            if (result.ok) {
                if (this.currentSessions) {
                    this.currentSessions = this.currentSessions.filter((s) => s.path !== sessionPath);
                }
                if (this.allSessions) {
                    this.allSessions = this.allSessions.filter((s) => s.path !== sessionPath);
                }
                const sessions = this.scope === "all" ? (this.allSessions ?? []) : (this.currentSessions ?? []);
                const showCwd = this.scope === "all";
                this.sessionList.setSessions(sessions, showCwd);
                const msg = result.method === "trash" ? "Session moved to trash" : "Session deleted";
                this.header.setStatusMessage({ type: "info", message: msg }, 2000);
                await this.refreshSessionsAfterMutation();
            }
            else {
                const errorMessage = result.error ?? "Unknown error";
                this.header.setStatusMessage({ type: "error", message: `Failed to delete: ${errorMessage}` }, 3000);
            }
            this.requestRender();
        };
        // Start loading current sessions immediately
        this.loadCurrentSessions();
    }
    loadCurrentSessions() {
        void this.loadScope("current", "initial");
    }
    enterRenameMode(sessionPath, currentName) {
        this.mode = "rename";
        this.renameTargetPath = sessionPath;
        this.renameInput.setValue(currentName ?? "");
        this.renameInput.focused = true;
        const panel = new Container();
        panel.addChild(new Text(theme.bold("Rename Session"), 1, 0));
        panel.addChild(new Spacer(1));
        panel.addChild(this.renameInput);
        panel.addChild(new Spacer(1));
        panel.addChild(new Text(theme.fg("muted", `${keyText("tui.select.confirm")} Save · ${keyText("tui.select.cancel")} Cancel`), 1, 0));
        this.buildBaseLayout(panel, { showHeader: false });
        this.requestRender();
    }
    exitRenameMode() {
        this.mode = "list";
        this.renameTargetPath = null;
        this.buildBaseLayout(this.sessionList);
        this.requestRender();
    }
    async confirmRename(value) {
        const next = value.trim();
        if (!next)
            return;
        const target = this.renameTargetPath;
        if (!target) {
            this.exitRenameMode();
            return;
        }
        // Find current name for callback
        const renameSession = this.renameSession;
        if (!renameSession) {
            this.exitRenameMode();
            return;
        }
        try {
            await renameSession(target, next);
            await this.refreshSessionsAfterMutation();
        }
        finally {
            this.exitRenameMode();
        }
    }
    async loadScope(scope, reason) {
        const showCwd = scope === "all";
        // Mark loading
        if (scope === "current") {
            this.currentLoading = true;
        }
        else {
            this.allLoading = true;
        }
        const seq = scope === "all" ? ++this.allLoadSeq : undefined;
        this.header.setScope(scope);
        this.header.setLoading(true);
        this.requestRender();
        const onProgress = (loaded, total) => {
            if (scope !== this.scope)
                return;
            if (seq !== undefined && seq !== this.allLoadSeq)
                return;
            this.header.setProgress(loaded, total);
            this.requestRender();
        };
        try {
            const sessions = await (scope === "current"
                ? this.currentSessionsLoader(onProgress)
                : this.allSessionsLoader(onProgress));
            if (scope === "current") {
                this.currentSessions = sessions;
                this.currentLoading = false;
            }
            else {
                this.allSessions = sessions;
                this.allLoading = false;
            }
            if (scope !== this.scope)
                return;
            if (seq !== undefined && seq !== this.allLoadSeq)
                return;
            this.header.setLoading(false);
            this.sessionList.setSessions(sessions, showCwd);
            this.requestRender();
            if (scope === "all" && sessions.length === 0 && (this.currentSessions?.length ?? 0) === 0) {
                this.onCancel();
            }
        }
        catch (err) {
            if (scope === "current") {
                this.currentLoading = false;
            }
            else {
                this.allLoading = false;
            }
            if (scope !== this.scope)
                return;
            if (seq !== undefined && seq !== this.allLoadSeq)
                return;
            const message = err instanceof Error ? err.message : String(err);
            this.header.setLoading(false);
            this.header.setStatusMessage({ type: "error", message: `Failed to load sessions: ${message}` }, 4000);
            if (reason === "initial") {
                this.sessionList.setSessions([], showCwd);
            }
            this.requestRender();
        }
    }
    toggleSortMode() {
        // Cycle: threaded -> recent -> relevance -> threaded
        this.sortMode = this.sortMode === "threaded" ? "recent" : this.sortMode === "recent" ? "relevance" : "threaded";
        this.header.setSortMode(this.sortMode);
        this.sessionList.setSortMode(this.sortMode);
        this.requestRender();
    }
    toggleNameFilter() {
        this.nameFilter = this.nameFilter === "all" ? "named" : "all";
        this.header.setNameFilter(this.nameFilter);
        this.sessionList.setNameFilter(this.nameFilter);
        this.requestRender();
    }
    async refreshSessionsAfterMutation() {
        await this.loadScope(this.scope, "refresh");
    }
    toggleScope() {
        if (this.scope === "current") {
            this.scope = "all";
            this.header.setScope(this.scope);
            if (this.allSessions !== null) {
                this.header.setLoading(false);
                this.sessionList.setSessions(this.allSessions, true);
                this.requestRender();
                return;
            }
            if (!this.allLoading) {
                void this.loadScope("all", "toggle");
            }
            return;
        }
        this.scope = "current";
        this.header.setScope(this.scope);
        this.header.setLoading(this.currentLoading);
        this.sessionList.setSessions(this.currentSessions ?? [], false);
        this.requestRender();
    }
    getSessionList() {
        return this.sessionList;
    }
}
//# sourceMappingURL=session-selector.js.map