// Home — the page you open to do something, not to read a report.
//
// It used to lead with a diagram of the attached monitor: DP-2, 4500 x 3000,
// 1.13x scale, XRGB2101010. That is Displays-page data, it was the largest
// thing on the screen, and nobody has ever needed it here. Below it sat a
// permanently open search field for a weather location that is set about once a
// year, and then roughly half a page of nothing.
//
// What Panama already knows is the useful material: whether anything needs
// attention, what is running, and the two or three things worth doing next. A
// finding is shown when there is one and the page is quiet when there is not,
// which is the same shape the Firewall and Containers pages use.
//
// Weather stays. It is the one genuinely ambient thing here, and it belongs
// next to a greeting rather than in a card of its own with a search box open.

import QtQuick
import qs.config
import qs.services

SettingsPage {
    id: root

    readonly property int openedHour: new Date().getHours()
    readonly property string greeting: openedHour < 12
        ? "Good morning"
        : (openedHour < 18 ? "Good afternoon" : "Good evening")

    // Findings, in the order they deserve attention. Each names the page that
    // can actually resolve it, because a home page that reports a problem it
    // cannot help with is just an alarm.
    readonly property var findings: {
        const found = [];
        const exposed = Firewall.exposedDataStores ?? [];
        if (exposed.length > 0) {
            found.push({
                label: exposed.length === 1
                    ? "A database is reachable from your network"
                    : "Databases are reachable from your network",
                detail: exposed.map(entry => String(entry.name)).join(" and ")
                    + ", published on every interface",
                page: "firewall",
                action: "Review"
            });
        }
        if (Updates.securityCount > 0) {
            found.push({
                label: Updates.securityCount + " update"
                    + (Updates.securityCount === 1 ? "" : "s") + " carry a security advisory",
                detail: "Worth installing before the rest",
                page: "updates",
                action: "Open"
            });
        }
        if (Updates.rebootNeeded) {
            found.push({
                label: "A newer kernel is installed than the one running",
                detail: "Restart to use it",
                page: "updates",
                action: "Open"
            });
        }
        if (Health.summary?.errors > 0 || Health.summary?.warnings > 0) {
            const count = Number(Health.summary?.errors ?? 0) + Number(Health.summary?.warnings ?? 0);
            found.push({
                label: count + " health check" + (count === 1 ? "" : "s") + " need attention",
                detail: "Something the desktop owns is not in its expected state",
                page: "services",
                action: "Open"
            });
        }
        return found;
    }

    // One line of everything that is fine, so the quiet case still says
    // something rather than showing an empty page.
    readonly property string reassurance: {
        const parts = [];
        if (Health.checks.length > 0)
            parts.push(Health.checks.length + " health checks pass");
        if (Disks.rootFilesystem)
            parts.push(Disks.formatBytes(Number(Disks.rootFilesystem.available ?? 0)) + " free");
        const newest = Snapshots.configs.length > 0
            ? (Snapshots.configs[0].snapshots ?? [])[0]
            : null;
        if (newest)
            parts.push("snapshots ran at " + root.clockOf(String(newest.date ?? "")));
        return parts.join(" · ");
    }

    // snapper prints a full date; only the time is wanted in a summary line.
    function clockOf(stamp: string): string {
        const match = /(\d{1,2}:\d{2})(?::\d{2})?\s*(AM|PM)?/i.exec(stamp);
        if (!match)
            return stamp;
        return match[2] ? match[1] + " " + match[2].toUpperCase() : match[1];
    }

    title: `${root.greeting}, Gabriel`
    lede: Weather.available
        ? Math.round(Weather.temperature) + Weather.unitSuffix + " and "
          + Weather.description.toLowerCase() + " in " + Settings.weatherLocation
        : "Your desktop is configured and ready."

    Component.onCompleted: {
        if (!Firewall.scanned)
            Firewall.refresh();
        if (!Containers.scanned)
            Containers.refresh();
        if (!Snapshots.scanned)
            Snapshots.refresh();
        if (!Disks.scanned)
            Disks.refresh();
    }

    // ── What you came here to do ────────────────────────────────────────────

    Grid {
        id: doing

        width: parent.width
        columns: width >= 720 ? 2 : 1
        columnSpacing: 16
        rowSpacing: 16

        SettingsCard {
            width: doing.columns === 2
                ? (doing.width - doing.columnSpacing) / 2
                : doing.width
            title: "Focus"
            subtitle: FocusSession.active
                ? "A session is running · " + FocusSession.remainingText + " left"
                : (FocusModes.active
                    ? FocusModes.activeName + " is on because " + FocusModes.activeReason
                    : (Notifs.doNotDisturb
                        ? "Do Not Disturb is on"
                        : "Nothing is quieting this machine"))

            SettingRow {
                label: FocusSession.active ? "End the session" : "Start a focus session"
                detail: FocusSession.active
                    ? "Puts Do Not Disturb and Caffeine back as they were"
                    : Settings.focusDurationMinutes + " minutes · Super+Shift+F"
                controlWidth: 120

                SettingsButton {
                    anchors.right: parent.right
                    anchors.verticalCenter: parent.verticalCenter
                    text: FocusSession.active ? "End" : "Start"
                    tone: FocusSession.active ? "normal" : "accent"
                    onClicked: FocusSession.active ? FocusSession.end(false) : FocusSession.startDefault()
                }
            }

            SettingRow {
                label: "Do Not Disturb"
                detail: FocusModes.active
                    ? "Held on by the " + FocusModes.activeName + " mode"
                    : "Banners are held; the notification centre still fills"
                divider: false
                controlWidth: 48

                SettingsToggle {
                    anchors.right: parent.right
                    anchors.verticalCenter: parent.verticalCenter
                    enabled: !FocusModes.active && !FocusSession.active
                    checked: Notifs.doNotDisturb
                    onToggled: value => Notifs.doNotDisturb = value
                }
            }
        }

        SettingsCard {
            width: doing.columns === 2
                ? (doing.width - doing.columnSpacing) / 2
                : doing.width
            title: "Right now"
            subtitle: Containers.running > 0
                ? Containers.running + " of " + Containers.total + " containers running"
                : "No containers are running"

            TextRow {
                label: Containers.running > 0
                    ? Containers.projects.filter(project => project.running > 0)
                        .map(project => String(project.title)).join(", ")
                    : "Nothing to report"
                detail: Containers.running > 0
                    ? "Started for development, still up"
                    : "Start a stack from the Containers page"
                value: ""
            }

            ActionRow {
                label: "Containers"
                detail: "Projects, what they expose, and what they cost"
                action: "Open"
                divider: false
                onTriggered: ShellState.settingsPage = "containers"
            }
        }
    }

    // ── This machine ────────────────────────────────────────────────────────

    SettingsCard {
        title: "This machine"
        subtitle: root.reassurance

        TextRow {
            visible: root.findings.length === 0
            label: "Nothing needs your attention"
            detail: "Anything worth acting on would appear here."
            value: ""
            divider: false
        }

        Repeater {
            model: root.findings

            delegate: SettingRow {
                required property var modelData
                required property int index
                width: parent.width
                label: String(modelData.label ?? "")
                detail: String(modelData.detail ?? "")
                controlWidth: 110
                divider: index < root.findings.length - 1

                SettingsButton {
                    anchors.right: parent.right
                    anchors.verticalCenter: parent.verticalCenter
                    text: String(modelData.action ?? "Open")
                    onClicked: ShellState.settingsPage = String(modelData.page)
                }
            }
        }
    }

    // ── Worth doing, when there is something ────────────────────────────────

    SettingsCard {
        visible: Updates.total > 0 || Containers.reclaimable > 0
        title: "Do next"
        subtitle: "Small things this machine is waiting on."

        ActionRow {
            visible: Updates.total > 0
            label: "Install " + Updates.total + " update" + (Updates.total === 1 ? "" : "s")
            detail: "Packages, applications and firmware, from wherever each comes from"
            action: "Open"
            divider: Containers.reclaimable > 0
            onTriggered: ShellState.settingsPage = "updates"
        }

        ActionRow {
            visible: Containers.reclaimable > 0
            label: "Reclaim " + Containers.formatBytes(Containers.reclaimable)
            detail: "Container images and volumes nothing references"
            action: "Review"
            divider: false
            onTriggered: ShellState.settingsPage = "containers"
        }
    }

    // ── Weather ─────────────────────────────────────────────────────────────

    SettingsCard {
        title: "Weather"
        subtitle: "Shown above and in the date menu."

        // The location is set roughly once a year, so the search that changes it
        // is behind a press rather than permanently open.
        PickerRow {
            id: locationPicker

            label: "Location"
            detail: "Only the search term is sent; the name is a label kept on this machine"
            value: Settings.weatherLocation

            LocationPicker {
                width: parent.width
                onPicked: locationPicker.collapse()
            }
        }

        ChoiceRow { setting: "temperatureUnit" }
        SliderRow { setting: "weatherRefreshMinutes"; divider: false }
    }
}
