"""Cursor usage tray application."""
from __future__ import annotations

import queue
import sys
import threading
import tkinter as tk
import webbrowser
from collections.abc import Callable

if sys.platform == "linux":
    from linux_setup import configure_linux_runtime

    configure_linux_runtime()

from pystray import Icon, Menu, MenuItem

from api import UsageSnapshot, fetch_usage, format_tray_tooltip
from auth import get_plan_label, get_user_label
from config_store import load_config, save_window_margins
from errors import log_error, user_facing_error
from tray_icon import render_tray_icon
from ui import UsageWindow


class TrayApp:
    def __init__(self) -> None:
        self._config = load_config()
        display = self._config.get("display", {})
        margin_right = int(display.get("margin_right", 10))
        margin_above_taskbar = int(display.get("margin_above_taskbar", 10))
        legacy_position = None
        if "position_x" in display and "position_y" in display:
            legacy_position = (int(display["position_x"]), int(display["position_y"]))

        self._refresh_secs = int(display.get("refresh_interval_secs", 60))
        self._plan_label = get_plan_label()
        self._user_label = get_user_label()
        self._snapshot: UsageSnapshot | None = None
        self._fetching = False
        self._ui_queue: queue.SimpleQueue[Callable[[], None]] = queue.SimpleQueue()
        self._tk = tk.Tk()
        self._tk.withdraw()
        self._window = UsageWindow(
            self._tk,
            on_refresh=self.refresh,
            margin_right=margin_right,
            margin_above_taskbar=margin_above_taskbar,
            legacy_position=legacy_position,
            on_margins_saved=self._save_window_margins,
            plan_label=self._plan_label,
            user_label=self._user_label,
            refresh_interval_secs=self._refresh_secs,
        )
        self._icon = Icon(
            "cursor-usage",
            render_tray_icon(None),
            "Cursor Usage",
            menu=Menu(
                MenuItem("Toggle", self._toggle_window, default=True),
                MenuItem("Refresh", self.refresh),
                MenuItem(
                    "Open Dashboard",
                    lambda *_: webbrowser.open("https://cursor.com/dashboard/usage"),
                ),
                MenuItem("Quit", self._quit),
            ),
        )

    def _post_ui(self, callback: Callable[[], None]) -> None:
        self._ui_queue.put(callback)

    def _poll_ui_queue(self) -> None:
        while True:
            try:
                callback = self._ui_queue.get_nowait()
            except queue.Empty:
                break
            callback()
        self._tk.after(16, self._poll_ui_queue)

    def _save_window_margins(self, margin_right: int, margin_above_taskbar: int) -> None:
        save_window_margins(margin_right, margin_above_taskbar)
        display = self._config.setdefault("display", {})
        display["margin_right"] = margin_right
        display["margin_above_taskbar"] = margin_above_taskbar
        display.pop("position_x", None)
        display.pop("position_y", None)

    def _tooltip(self) -> str:
        if not self._snapshot:
            return "Cursor Usage"
        return format_tray_tooltip(self._snapshot, self._plan_label)

    def _update_icon(self, percent: float | None = None) -> None:
        self._icon.icon = render_tray_icon(percent)

    def _toggle_window(self, *_args) -> None:
        self._post_ui(self._window.toggle)

    def _quit(self, *_args) -> None:
        self._icon.stop()
        self._post_ui(self._tk.quit)

    def _apply_snapshot(self, snapshot: UsageSnapshot) -> None:
        self._snapshot = snapshot
        plan = self._plan_label
        self._icon.title = format_tray_tooltip(snapshot, plan)
        self._update_icon(snapshot.total_percent_used)

        def update_ui() -> None:
            self._window.set_plan_label(plan)
            self._window.render(snapshot)

        self._post_ui(update_ui)

    def _apply_error(self, message: str) -> None:
        self._icon.title = "Cursor Usage — error"

        def update_ui() -> None:
            self._window.render_error(message)

        self._post_ui(update_ui)

    def _fetch(self) -> None:
        if self._fetching:
            return
        self._fetching = True
        self._post_ui(self._window.reset_refresh_countdown)

        def worker() -> None:
            try:
                snapshot = fetch_usage()
                self._apply_snapshot(snapshot)
            except Exception as exc:  # noqa: BLE001
                log_error(exc)
                self._apply_error(user_facing_error(exc))
            finally:
                self._fetching = False

        threading.Thread(target=worker, daemon=True).start()

    def refresh(self, *_args) -> None:
        self._fetch()

    def _schedule_refresh(self) -> None:
        self._fetch()
        self._tk.after(self._refresh_secs * 1000, self._schedule_refresh)

    def run(self) -> None:
        self._tk.after(16, self._poll_ui_queue)
        threading.Thread(target=self._icon.run, daemon=True).start()
        self._tk.after(500, self._schedule_refresh)
        self._tk.mainloop()
        sys.exit(0)


def main() -> None:
    TrayApp().run()


if __name__ == "__main__":
    main()
