pragma Singleton
pragma ComponentBehavior: Bound

import QtQuick
import Qt.labs.folderlistmodel
import Quickshell
import Quickshell.Io
import qs.Common

Singleton {
    id: root

    readonly property string _homeDir: Quickshell.env("HOME") || ""
    readonly property string _xdgDataHome: Quickshell.env("XDG_DATA_HOME") || (_homeDir + "/.local/share")
    readonly property string trashFilesDir: _xdgDataHome + "/Trash/files"

    property int count: 0
    readonly property bool isEmpty: count === 0

    property var availableFileManagers: ["default"]
    property string defaultFileManagerLabel: "default (xdg-open)"

    signal emptyTrashConfirmRequested(int itemCount)

    FolderListModel {
        id: homeTrashModel
        folder: "file://" + root.trashFilesDir
        showDirs: true
        showFiles: true
        showHidden: true
        showDotAndDotDot: false
        sortField: FolderListModel.Name
        nameFilters: ["*"]
    }

    Connections {
        target: homeTrashModel
        function onCountChanged() {
            root.refreshCount();
        }
    }

    Process {
        id: detectProc
        running: false
        command: ["sh", "-c", "for fm in nautilus thunar dolphin nemo caja pcmanfm pcmanfm-qt krusader; do command -v $fm >/dev/null 2>&1 && echo $fm; done"]
        stdout: StdioCollector {
            onStreamFinished: {
                const detected = (text || "").split("\n").map(s => s.trim()).filter(s => s.length > 0);
                root.availableFileManagers = ["default"].concat(detected).concat(["custom"]);
            }
        }
    }

    Component.onCompleted: {
        Paths.trashHandler = (path, callback) => trashPath(path, callback);
        detectProc.running = true;
        refreshCount();
    }

    function refreshCount() {
        Proc.runCommand("trash-count", [Proc.dmsBin, "trash", "count"], (output, exitCode) => {
            if (exitCode !== 0) {
                root.count = homeTrashModel.count;
                return;
            }
            const n = parseInt((output || "").trim(), 10);
            root.count = isNaN(n) ? homeTrashModel.count : n;
        });
    }

    function trashPath(path, callback) {
        if (!path) {
            if (callback)
                callback(false, "empty path");
            return;
        }
        Proc.runCommand(null, [Proc.dmsBin, "trash", "put", path], (output, exitCode) => {
            const ok = exitCode === 0;
            if (!ok)
                ToastService.showError(I18n.tr("Failed to move to trash"), path);
            refreshCount();
            if (callback)
                callback(ok, output);
        });
    }

    function openTrash() {
        const choice = SettingsData.dockTrashFileManager || "default";
        switch (choice) {
        case "default":
            Quickshell.execDetached(["xdg-open", "trash:///"]);
            return;
        case "custom":
            openCustom();
            return;
        }
        if (availableFileManagers.indexOf(choice) < 0) {
            ToastService.showInfo(I18n.tr("Cannot open trash: '%1' is not installed").arg(choice), I18n.tr("Pick a different file manager in Settings → Dock → Trash."));
            return;
        }
        Quickshell.execDetached([choice, "trash:///"]);
    }

    function openCustom() {
        const cmd = (SettingsData.dockTrashCustomCommand || "").trim();
        if (!cmd) {
            ToastService.showInfo(I18n.tr("Cannot open trash: no custom command set"), I18n.tr("Configure one in Settings → Dock → Trash."));
            return;
        }
        Proc.runCommand(null, ["sh", "-c", cmd], (output, exitCode) => {
            if (exitCode !== 0) {
                ToastService.showError(I18n.tr("Trash command failed (exit %1)").arg(exitCode), I18n.tr("Check your custom command in Settings → Dock → Trash."));
            }
        }, 0, Proc.noTimeout);
    }

    function requestEmptyTrash() {
        if (isEmpty)
            return;
        emptyTrashConfirmRequested(count);
    }

    function emptyTrash() {
        Proc.runCommand("trash-empty", [Proc.dmsBin, "trash", "empty"], (output, exitCode) => {
            if (exitCode !== 0)
                ToastService.showError(I18n.tr("Failed to empty trash"), output || "");
            refreshCount();
        });
    }
}
