// Home — the page you open to do something, not to read a report.
//
// The Overview tab of the Home category. Quick actions sit under the greeting
// as tiles; findings follow; then two glance cards into the sibling tabs (My
// Home, Phone), the next calendar event, and weather. The old Focus and
// containers cards retired into the tiles and the System category; the
// reclaim-space prompt is gone on purpose — stopped development containers
// are not clutter, and prompting their deletion was a racket.

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 (Updates.total > 0) {
            found.push({
                label: "Install " + Updates.total + " update" + (Updates.total === 1 ? "" : "s"),
                detail: "Packages, applications and firmware, from wherever each comes from",
                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.availBytes ?? 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];
    }

    // Greets whoever is signed in, from the same accountsservice record the
    // lock screen shows. This once hardcoded the author's first name, which
    // made the first screen of Settings wrong for every other human.
    readonly property string greetingName: {
        if (!UserAccounts.me)
            return "";
        const full = UserAccounts.displayName(UserAccounts.me);
        return full.split(" ")[0] || "";
    }

    // What the glance cards say about the sibling tabs.
    readonly property var lightsOn: HomeAssistant.catalog.filter(entity => entity.active === true)
    readonly property string myHomeGlance: {
        if (HomeAssistant.lastError === "not-configured")
            return "Set up Home Assistant";
        if (root.lightsOn.length === 0)
            return "No lights are on";
        const names = root.lightsOn.slice(0, 2).map(entity => String(entity.name ?? entity.sourceName)).join(", ");
        return root.lightsOn.length + (root.lightsOn.length === 1 ? " light on · " : " lights on · ") + names;
    }
    readonly property string phoneGlance: {
        if (!KdeConnect.preferredPhone)
            return "No paired phone";
        const parts = [String(KdeConnect.preferredPhone.name)];
        if (KdeConnect.phoneBattery)
            parts.push(KdeConnect.phoneBattery.charge + "%");
        parts.push(KdeConnect.phoneReachable ? "nearby" : "away");
        return parts.join(" · ");
    }

    // The next timed calendar event, worded for a card.
    readonly property string nextEventWhen: {
        const event = CalendarAgenda.nextEvent;
        if (!event)
            return "";
        const start = new Date(Number(event.start) * 1000);
        const clock = start.toLocaleTimeString(Qt.locale(), Locale.ShortFormat);
        const today = new Date();
        const sameDay = start.getFullYear() === today.getFullYear()
            && start.getMonth() === today.getMonth() && start.getDate() === today.getDate();
        return sameDay ? clock + " today" : clock + " " + start.toLocaleDateString(Qt.locale(), "dddd");
    }

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

    // These scans also feed the System category's tab gating (Containers,
    // Snapshots), so they fire when Settings opens even though this page no
    // longer renders their cards.
    Component.onCompleted: {
        if (!Firewall.scanned)
            Firewall.refresh();
        if (!Containers.scanned)
            Containers.refresh();
        if (!Snapshots.scanned)
            Snapshots.refresh();
        if (!Disks.scanned)
            Disks.refresh();
    }

    // ── Quick actions ───────────────────────────────────────────────────────

    Grid {
        id: quick

        width: parent.width
        columns: width >= 640 ? 5 : 2
        columnSpacing: 10
        rowSpacing: 10

        readonly property real tileWidth: (width - (columns - 1) * columnSpacing) / columns

        HomeQuickTile {
            width: quick.tileWidth
            glyph: "\u{F051F}"
            label: FocusSession.active ? "End focus" : "Focus session"
            caption: FocusSession.active
                ? FocusSession.remainingText + " left · tap to end"
                : Settings.focusDurationMinutes + " min · Super+Shift+F"
            onActivated: FocusSession.active ? FocusSession.end(false) : FocusSession.startDefault()
        }

        HomeQuickTile {
            width: quick.tileWidth
            glyph: "\u{F009A}"
            glyphColor: Notifs.doNotDisturb ? Theme.warn : Theme.accent
            label: "Do Not Disturb"
            interactive: !FocusModes.active && !FocusSession.active
            caption: {
                if (FocusModes.active)
                    return "Held by the " + FocusModes.activeName + " mode";
                if (FocusSession.active)
                    return "Held by the focus session";
                return Notifs.doNotDisturb ? "On — tap to allow banners" : "Off — tap to hold banners";
            }
            onActivated: Notifs.doNotDisturb = !Notifs.doNotDisturb
        }

        HomeQuickTile {
            width: quick.tileWidth
            glyph: "\u{F0493}"
            glyphColor: Health.status === "error"
                ? Theme.danger : (Health.status === "warning" ? Theme.warn : Theme.ok)
            label: "Health"
            caption: {
                if (Health.checks.length === 0)
                    return "Checking the desktop";
                const count = Number(Health.summary?.errors ?? 0) + Number(Health.summary?.warnings ?? 0);
                return count > 0 ? count + " need attention" : Health.checks.length + " checks pass";
            }
            onActivated: ShellState.openSettings("services")
        }

        HomeQuickTile {
            width: quick.tileWidth
            glyph: "\u{F0954}"
            label: "Snapshots"
            caption: {
                const newest = Snapshots.configs.length > 0
                    ? (Snapshots.configs[0].snapshots ?? [])[0] : null;
                if (newest)
                    return "Ran at " + root.clockOf(String(newest.date ?? ""));
                return Snapshots.configs.length > 0 ? "Configured" : "Not protected";
            }
            onActivated: ShellState.openSettings("snapshots")
        }

        HomeQuickTile {
            width: quick.tileWidth
            glyph: "\u{F02CA}"
            label: "Storage"
            caption: Disks.rootFilesystem
                ? Disks.formatBytes(Number(Disks.rootFilesystem.availBytes ?? 0)) + " free"
                : "Reading the drive"
            onActivated: ShellState.openSettings("storage")
        }
    }

    // ── 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)
                }
            }
        }
    }

    // ── Glances into the sibling tabs ───────────────────────────────────────

    Grid {
        id: glances

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

        readonly property real cardWidth: columns === 2 ? (width - columnSpacing) / 2 : width

        Repeater {
            model: [
                { glyph: "\u{F0335}", title: "My Home", sub: root.myHomeGlance, page: "my-home" },
                { glyph: "\u{F011C}", title: "Phone", sub: root.phoneGlance, page: "phone" }
            ]

            delegate: Rectangle {
                id: glance

                required property var modelData

                width: glances.cardWidth
                height: 74
                radius: 14
                color: glanceArea.containsMouse
                    ? Theme.alpha(Theme.bgPanel, 0.95)
                    : Theme.alpha(Theme.bgPanel, 0.72)
                border.width: 1
                border.color: Theme.alpha(Theme.fg, 0.07)

                Text {
                    id: glanceGlyph
                    anchors.left: parent.left
                    anchors.leftMargin: 16
                    anchors.verticalCenter: parent.verticalCenter
                    text: String(glance.modelData.glyph)
                    color: Theme.accent
                    font.family: Theme.fontMono
                    font.pixelSize: 19
                }

                Column {
                    anchors.left: glanceGlyph.right
                    anchors.leftMargin: 14
                    anchors.right: chevron.left
                    anchors.rightMargin: 10
                    anchors.verticalCenter: parent.verticalCenter
                    spacing: 3

                    Text {
                        text: String(glance.modelData.title)
                        color: Theme.fg
                        font.family: Theme.fontFamily
                        font.pixelSize: Theme.fontSizeLarge
                        font.weight: Font.DemiBold
                    }

                    Text {
                        width: parent.width
                        text: String(glance.modelData.sub)
                        color: Theme.fgDim
                        font.family: Theme.fontFamily
                        font.pixelSize: Theme.fontSizeSmall
                        elide: Text.ElideRight
                    }
                }

                Text {
                    id: chevron
                    anchors.right: parent.right
                    anchors.rightMargin: 15
                    anchors.verticalCenter: parent.verticalCenter
                    text: "›"
                    color: Theme.fgMuted
                    font.family: Theme.fontFamily
                    font.pixelSize: 18
                }

                MouseArea {
                    id: glanceArea
                    anchors.fill: parent
                    hoverEnabled: true
                    cursorShape: Qt.PointingHandCursor
                    onClicked: ShellState.openSettings(String(glance.modelData.page))
                }

                Accessible.role: Accessible.Button
                Accessible.name: "Open " + String(glance.modelData.title)
            }
        }
    }

    // ── Today ───────────────────────────────────────────────────────────────

    SettingsCard {
        visible: CalendarAgenda.available && CalendarAgenda.nextEvent !== null
        title: "Today"

        SettingRow {
            label: CalendarAgenda.nextEvent
                ? String(CalendarAgenda.nextEvent.summary) + " — " + root.nextEventWhen
                : ""
            detail: "Next on your calendar"
            divider: false
            controlWidth: 110

            SettingsButton {
                anchors.right: parent.right
                anchors.verticalCenter: parent.verticalCenter
                text: String(CalendarAgenda.nextEvent?.joinUrl ?? "").startsWith("https://")
                    ? "Join" : "Open"
                onClicked: {
                    const event = CalendarAgenda.nextEvent;
                    if (!event)
                        return;
                    if (String(event.joinUrl ?? "").startsWith("https://"))
                        CalendarAgenda.join(event);
                    else
                        CalendarAgenda.openEvent(event);
                }
            }
        }
    }

    // ── 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 !== "" ? Settings.weatherLocation : "Not set — choose one to see weather"

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

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