"""Мост Python ↔ HTML-панель (pywebview)."""

from __future__ import annotations

import time
from typing import Any

from api_client import BotApiClient, ConnectionConfig
from desktop_notify import notify as desktop_notify
from desktop_notify import play_notify_sound as _play_notify_sound_fn
from telemetry_client import send_telemetry_from_radar
from tray_service import show_window as tray_show_window


class PanelBridge:
    def __init__(self):
        self.config = ConnectionConfig.load()
        self.client = BotApiClient(self.config)

    def _reload_client(self):
        self.client = BotApiClient(self.config)

    def _run(self, fn) -> dict[str, Any]:
        t0 = time.perf_counter()
        try:
            data = fn()
            return {
                "ok": True,
                "data": data,
                "ms": int((time.perf_counter() - t0) * 1000),
            }
        except Exception as e:
            return {"ok": False, "error": str(e)}

    def load_config(self) -> dict:
        return {
            "ok": True,
            "data": {
                "host": self.config.host,
                "port": self.config.port,
                "token": self.config.token,
                "radar_session": self.config.radar_session,
                "telegram_bot_username": self.config.telegram_bot_username,
                "notify_sound_enabled": self.config.notify_sound_enabled,
                "admin_capable": self.config.admin_capable,
            },
        }

    def _persist_radar_session(self, data: dict, telemetry_event: str | None = None) -> None:
        token = str(data.get("session_token") or "")
        if token:
            self.config.radar_session = token
        if data.get("is_admin"):
            self.config.admin_capable = True
        self.config.save()
        if token:
            self.client.set_radar_session(token)
        if telemetry_event:
            send_telemetry_from_radar(
                telemetry_event,
                self.config.guest_device_id or "",
                data,
            )

    def save_notify_sound(self, enabled: bool) -> dict:
        self.config.notify_sound_enabled = bool(enabled)
        self.config.save()
        return {"ok": True}

    def get_autostart(self) -> dict:
        import autostart

        return {"ok": True, "data": autostart.get_state()}

    def set_autostart(self, enabled: bool) -> dict:
        import autostart

        try:
            state = autostart.set_enabled(bool(enabled))
            return {"ok": True, "data": {"enabled": state, "supported": True}}
        except Exception as e:
            return {"ok": False, "error": str(e)}

    def save_config(self, host: str, port: int, token: str, telegram_bot_username: str = "") -> dict:
        self.config = ConnectionConfig(
            host=str(host).strip() or "127.0.0.1",
            port=int(port),
            token=str(token).strip(),
            radar_session=self.config.radar_session,
            guest_device_id=self.config.guest_device_id,
            telegram_bot_username=str(telegram_bot_username or self.config.telegram_bot_username or "").strip(),
            notify_sound_enabled=self.config.notify_sound_enabled,
            admin_capable=self.config.admin_capable,
        )
        self.config.save()
        self._reload_client()
        return {"ok": True}

    def save_radar_session(self, token: str) -> dict:
        self.config.radar_session = str(token or "").strip()
        self.config.save()
        self.client.set_radar_session(self.config.radar_session)
        return {"ok": True}

    def radar_auth_guest(self) -> dict:
        def _go():
            data = self.client.radar_auth_guest()
            self._persist_radar_session(data, "open")
            return data

        return self._run(_go)

    def radar_auth_telegram(self, payload: dict) -> dict:
        def _go():
            data = self.client.radar_auth_telegram(payload or {})
            self._persist_radar_session(data, "login")
            return data

        return self._run(_go)

    def radar_auth_site_link(self, link: str) -> dict:
        def _go():
            data = self.client.radar_auth_site_link(link)
            self._persist_radar_session(data, "login")
            return data

        return self._run(_go)

    def start_site_auth(self) -> dict:
        import urllib.parse
        import webbrowser

        from panel_auth_server import wait_for_site_callback

        port = 9876
        callback = f"http://127.0.0.1:{port}/callback"
        url = (
            "https://axon-trade.com/ru/radar/panel-auth?callback="
            + urllib.parse.quote(callback, safe="")
        )

        def _go():
            webbrowser.open(url)
            result = wait_for_site_callback(port=port, timeout=180.0)
            link = str(result.get("link") or "").strip()
            if not link:
                err = str(result.get("error") or "").strip()
                raise RuntimeError(err or "Вход отменён или не завершён")
            data = self.client.radar_auth_site_link(link)
            self._persist_radar_session(data, "login")
            return data

        return self._run(_go)

    def telemetry_event(self, event: str) -> dict:
        def _go():
            user = {}
            try:
                user = self.client.radar_me()
            except Exception:
                pass
            send_telemetry_from_radar(
                str(event or "").strip() or "event",
                self.config.guest_device_id or "",
                user,
            )
            return {"sent": True}

        return self._run(_go)

    def open_external(self, url: str) -> dict:
        import webbrowser

        target = str(url or "").strip()
        if not target:
            return {"ok": False, "error": "empty url"}
        webbrowser.open(target)
        return {"ok": True}

    def radar_me(self) -> dict:
        return self._run(self.client.radar_me)

    def radar_refresh(self) -> dict:
        return self._run(self.client.radar_refresh)

    def radar_analyze(self, query: str) -> dict:
        return self._run(lambda: self.client.radar_analyze(str(query or "").strip()))

    def radar_ban_list(self) -> dict:
        return self._run(self.client.radar_ban_list)

    def radar_tracking(self) -> dict:
        return self._run(self.client.radar_tracking)

    def radar_signals(self, hours: int = 168, limit: int = 200) -> dict:
        return self._run(lambda: self.client.radar_signals(int(hours), int(limit)))

    def radar_signals_outcomes(self, hours: int = 168, limit: int = 200) -> dict:
        return self._run(
            lambda: self.client.radar_signals_outcomes(int(hours), int(limit))
        )

    def radar_tracking_detail(self, signal_id: str) -> dict:
        return self._run(lambda: self.client.radar_tracking_detail(str(signal_id)))

    def radar_tracking_chart(self, signal_id: str, timeframe: str = "1m") -> dict:
        return self._run(lambda: self.client.radar_tracking_chart(str(signal_id), str(timeframe or "1m")))

    def radar_tracking_live(self, signal_id: str) -> dict:
        return self._run(lambda: self.client.radar_tracking_live(str(signal_id)))

    def health(self) -> dict:
        return self._run(self.client.health)

    def health_quick(self) -> dict:
        return self._run(lambda: self.client.health(timeout=4))

    def status(self) -> dict:
        return self._run(self.client.status)

    def get_settings(self) -> dict:
        return self._run(self.client.get_settings)

    def update_settings(self, payload: dict) -> dict:
        return self._run(lambda: self.client.update_settings(payload or {}))

    def ban_list(self) -> dict:
        return self._run(self.client.ban_list)

    def add_ban(self, symbol: str, reason: str = "") -> dict:
        return self._run(lambda: self.client.add_ban(symbol, reason))

    def remove_ban(self, symbol: str) -> dict:
        return self._run(lambda: self.client.remove_ban(symbol))

    def signals(self, hours: int = 168, limit: int = 200) -> dict:
        return self._run(lambda: self.client.signals(int(hours), int(limit)))

    def restart(self) -> dict:
        return self._run(self.client.restart)

    def deploy_manifest(self) -> dict:
        return self._run(self.client.deploy_manifest)

    def deploy_files(self, files: list) -> dict:
        return self._run(lambda: self.client.deploy_files(files or []))

    def logs(self, lines: int = 250) -> dict:
        return self._run(lambda: self.client.logs(int(lines)))

    def tracking(self) -> dict:
        return self._run(self.client.tracking)

    def set_tracking(self, signal_id: str, enabled: bool) -> dict:
        return self._run(lambda: self.client.set_tracking(str(signal_id), bool(enabled)))

    def tracking_detail(self, signal_id: str) -> dict:
        return self._run(lambda: self.client.tracking_detail(str(signal_id)))

    def tracking_chart(self, signal_id: str, timeframe: str = "1m") -> dict:
        return self._run(lambda: self.client.tracking_chart(str(signal_id), str(timeframe or "1m")))

    def tracking_live(self, signal_id: str) -> dict:
        return self._run(lambda: self.client.tracking_live(str(signal_id)))

    def play_notify_sound(self, kind: str = "default") -> dict:
        ok = _play_notify_sound_fn(str(kind or "default"))
        return {"ok": ok}

    def is_panel_hidden(self) -> dict:
        from panel_state import is_panel_hidden as _hidden

        return {"ok": True, "data": {"hidden": _hidden()}}

    def pop_pending_notify_action(self) -> dict:
        from notify_ipc import pop_pending_for_js

        return {"ok": True, "data": {"action": pop_pending_for_js()}}

    def test_windows_toast(self) -> dict:
        ok = desktop_notify(
            "AXON Dump Radar — тест",
            "Windows toast работает",
            "signal",
            "signals",
            False,
        )
        return {"ok": ok}

    def desktop_notify(
        self,
        title: str,
        message: str,
        kind: str = "default",
        action: str = "",
        app_foreground: bool = False,
        force_toast: bool = False,
    ) -> dict:
        ok = desktop_notify(
            str(title or ""),
            str(message or ""),
            str(kind or "default"),
            str(action or ""),
            bool(app_foreground),
            bool(force_toast),
        )
        return {"ok": ok}

    def show_window(self) -> dict:
        try:
            import webview

            if webview.windows:
                tray_show_window(webview.windows[0])
            return {"ok": True}
        except Exception as e:
            return {"ok": False, "error": str(e)}

    def open_url(self, url: str) -> dict:
        import webbrowser

        try:
            webbrowser.open(str(url))
            return {"ok": True}
        except Exception as e:
            return {"ok": False, "error": str(e)}

    def panel_version_info(self) -> dict:
        from app_updater import current_version_info

        return self._run(current_version_info)

    def check_panel_update(self) -> dict:
        from app_updater import check_for_update

        return self._run(check_for_update)

    def skip_panel_update(self, version: str) -> dict:
        from app_updater import skip_update_version

        return self._run(lambda: skip_update_version(version))

    def apply_panel_update(self) -> dict:
        def _go():
            import webview

            from app_updater import download_and_apply_update

            win = webview.windows[0] if webview.windows else None
            return download_and_apply_update(win)

        return self._run(_go)
