"""Ambient macOS menu bar app."""

from __future__ import annotations

import threading
import webbrowser

import rumps

from hive_compute.app.benchmark_runner import run_app_benchmark
from hive_compute.app.debug_report import copy_debug_report_to_clipboard
from hive_compute.app.runtime_config import dashboard_url
from hive_compute.app.state import AppState, WorkerState
from hive_compute.app.worker_thread import AppWorkerThread

# Menu bar title glyphs — visible in the status bar at a glance
_ICONS = {
    WorkerState.STARTING: "◌",
    WorkerState.IDLE: "◉",
    WorkerState.WORKING: "◎",
    WorkerState.PAUSED: "◌",
    WorkerState.STOPPED: "○",
    WorkerState.ERROR: "⊗",
}

# Fetch pending payout from the coordinator every N timer ticks (tick = 3s → every 60s)
_PAYOUT_POLL_TICKS = 20


class AmbientApp(rumps.App):
    def __init__(self) -> None:
        super().__init__("Ambient", title=_ICONS[WorkerState.STARTING], quit_button=None)

        self.state = AppState()
        self.worker = AppWorkerThread(self.state)
        self._tick = 0
        self._benchmark_running = False

        # ── Menu items ────────────────────────────────────────────────────────
        self._status_item = rumps.MenuItem("Starting…")
        self._status_item.set_callback(None)

        self._payout_item = rumps.MenuItem("Pending payout: —")
        self._payout_item.set_callback(None)

        self._sync_item = rumps.MenuItem("Sync: waiting…")
        self._sync_item.set_callback(None)

        self._shards_item = rumps.MenuItem("Shards: 0")
        self._shards_item.set_callback(None)

        self._pause_item = rumps.MenuItem("Pause", callback=self._toggle_pause)
        self._benchmark_item = rumps.MenuItem("Run Benchmark", callback=self._run_benchmark)
        self._dashboard_item = rumps.MenuItem("Open Dashboard…", callback=self._open_dashboard)
        self._debug_item = rumps.MenuItem("Copy Debug Info", callback=self._copy_debug_info)
        self._quit_item = rumps.MenuItem("Quit Ambient", callback=self._quit)

        self.menu = [
            self._status_item,
            self._payout_item,
            self._sync_item,
            self._shards_item,
            None,
            self._pause_item,
            self._benchmark_item,
            None,
            self._dashboard_item,
            self._debug_item,
            None,
            self._quit_item,
        ]

        self.worker.start()
        rumps.Timer(self._refresh_ui, 3).start()

    # ── Periodic UI update ────────────────────────────────────────────────────

    def _refresh_ui(self, _timer) -> None:
        self._tick += 1
        s = self.state
        state = s.worker_state

        self.title = _ICONS.get(state, "◉")
        self._status_item.title = s.status_line()
        self._shards_item.title = f"Shards: {s.shards_completed}"
        self._pause_item.title = "Resume" if self.worker.is_paused() else "Pause"
        self._sync_item.title = s.payout_sync_status_line()

        # Fetch pending payout from coordinator periodically.
        if self._tick % _PAYOUT_POLL_TICKS == 1:
            threading.Thread(target=self._fetch_pending_payout, daemon=True).start()

        self._payout_item.title = f"Pending payout: ${s.earnings_dollars:.2f}"
        self._benchmark_item.title = "Benchmark in progress…" if self._benchmark_running else "Run Benchmark"
        self._benchmark_item.set_callback(None if self._benchmark_running else self._run_benchmark)

    def _fetch_pending_payout(self) -> None:
        client = self.worker.get_client()
        if client is None:
            return
        try:
            balance = client.fetch_pending_payout()
            if balance is not None:
                self.state.set_earnings(balance)
                self.state.mark_payout_sync_success()
                return
            self.state.mark_payout_sync_failure("empty coordinator response")
        except Exception:
            self.state.mark_payout_sync_failure("coordinator unreachable")

    # ── Menu actions ──────────────────────────────────────────────────────────

    def _toggle_pause(self, _sender) -> None:
        if self.worker.is_paused():
            self.worker.resume()
        else:
            self.worker.pause()

    def _run_benchmark(self, _sender) -> None:
        if self._benchmark_running:
            return
        self._benchmark_running = True
        rumps.notification(
            "Ambient",
            "Benchmark started",
            "The local runtime benchmark is running. This can take several minutes.",
        )
        threading.Thread(target=self._benchmark_worker, daemon=True).start()

    def _benchmark_worker(self) -> None:
        try:
            completed = run_app_benchmark(report_to_coordinator=True)
        except Exception as exc:
            rumps.notification("Ambient", "Benchmark failed", str(exc))
        else:
            details = []
            for line in completed.stdout.splitlines():
                if line.startswith("Saved Markdown:") or line.startswith("Saved JSON:"):
                    details.append(line.strip())
            detail = "\n".join(details) or "Results were saved under ~/.ambient/benchmarks."
            rumps.notification("Ambient", "Benchmark finished", detail)
        finally:
            self._benchmark_running = False

    def _open_dashboard(self, _sender) -> None:
        webbrowser.open(dashboard_url())

    def _copy_debug_info(self, _sender) -> None:
        try:
            copy_debug_report_to_clipboard(self.state)
        except Exception as exc:
            rumps.notification("Ambient", "Debug info failed", str(exc))
            return

        rumps.notification(
            "Ambient",
            "Debug info copied",
            "Paste it into support or a bug report.",
        )

    def _quit(self, _sender) -> None:
        self.worker.stop()
        rumps.quit_application()
