"""Startup splash for IuVe Connect Agent Console (0.2.1.0)."""

from __future__ import annotations

import threading
from concurrent.futures import ThreadPoolExecutor, TimeoutError as FuturesTimeoutError
from pathlib import Path
from typing import Callable

from ...core.version import AGENT_MVP_VERSION
from .window_branding import (
    apply_window_icon,
    apply_window_wm_class,
    center_window_on_primary_monitor,
    resolve_brand_icon_path,
)

LEGAL_COMPANY_NAME = "RECLAMA-VEREJAN I.I."
LEGAL_DEVELOPER_NAME = "Iurie Verejan"

SPLASH_WIDTH = 460
SPLASH_HEIGHT = 320
STAGE_TIMEOUT_SEC = 5.0
TOTAL_STARTUP_TIMEOUT_SEC = 15.0
SPLASH_STAGE_TIMEOUT_SECONDS = STAGE_TIMEOUT_SEC
SPLASH_MAX_SECONDS = TOTAL_STARTUP_TIMEOUT_SEC

# Process-wide guard: only one splash window per interpreter.
_active_splash_controller: "StartupSplashController | None" = None


def resolve_splash_logo_path() -> Path | None:
    return resolve_brand_icon_path()


class StartupSplashController:
    """GTK splash with staged startup progress before the main console window."""

    def __init__(
        self,
        *,
        status_adapter,
        gtk_module,
        adw_module,
        glib_module,
        translate_fn: Callable[[str], str],
    ) -> None:
        self._adapter = status_adapter
        self._gtk = gtk_module
        self._adw = adw_module
        self._glib = glib_module
        self._t = translate_fn
        self._window = None
        self._progress = None
        self._status_label = None
        self._on_ready: Callable[[], None] | None = None
        self._finished = False
        self._finish_lock = threading.Lock()

    def present(self, on_ready: Callable[[], None]) -> bool:
        """Show splash and run startup stages. Returns False if splash already active."""
        global _active_splash_controller
        if _active_splash_controller is not None:
            return False
        _active_splash_controller = self
        self._on_ready = on_ready
        self._window = self._gtk.Window()
        self._window.set_title("IuVe Connect")
        self._window.set_default_size(SPLASH_WIDTH, SPLASH_HEIGHT)
        self._window.set_resizable(False)
        self._window.set_decorated(True)
        self._window.set_modal(True)
        apply_window_icon(self._window)
        apply_window_wm_class(self._window)
        center_window_on_primary_monitor(
            self._window,
            width=SPLASH_WIDTH,
            height=SPLASH_HEIGHT,
            glib_idle_add=self._glib.idle_add,
        )

        root = self._gtk.Box(orientation=self._gtk.Orientation.VERTICAL, spacing=12)
        root.set_margin_top(24)
        root.set_margin_bottom(20)
        root.set_margin_start(24)
        root.set_margin_end(24)
        self._window.set_child(root)

        logo_path = resolve_splash_logo_path()
        if logo_path is not None:
            try:
                logo = self._gtk.Image.new_from_file(str(logo_path))
                logo.set_pixel_size(72)
                logo.set_halign(self._gtk.Align.CENTER)
                root.append(logo)
            except Exception:
                pass

        title = self._gtk.Label(label=self._t("splash.title"))
        title.add_css_class("title-1")
        title.set_halign(self._gtk.Align.CENTER)
        root.append(title)

        subtitle = self._gtk.Label(label=self._t("splash.subtitle"))
        subtitle.set_wrap(True)
        subtitle.set_halign(self._gtk.Align.CENTER)
        root.append(subtitle)

        version_label = self._gtk.Label(
            label=self._t("splash.version").format(version=AGENT_MVP_VERSION)
        )
        version_label.set_halign(self._gtk.Align.CENTER)
        root.append(version_label)

        self._progress = self._gtk.ProgressBar()
        self._progress.set_fraction(0.0)
        self._progress.set_show_text(True)
        root.append(self._progress)

        self._status_label = self._gtk.Label(label=self._t("splash.stage.init"))
        self._status_label.set_wrap(True)
        self._status_label.set_xalign(0.0)
        root.append(self._status_label)

        footer = self._gtk.Label(
            label=self._t("splash.footer").format(
                developer=LEGAL_DEVELOPER_NAME,
                company=LEGAL_COMPANY_NAME,
            )
        )
        footer.set_wrap(True)
        footer.set_xalign(0.5)
        footer.add_css_class("dim-label")
        root.append(footer)

        self._window.present()
        threading.Thread(target=self._run_startup_stages, daemon=True).start()
        return True

    def _set_stage(self, fraction: float, message_key: str) -> None:
        def _apply() -> bool:
            if self._progress is not None:
                self._progress.set_fraction(max(0.0, min(1.0, fraction)))
                self._progress.set_text(f"{int(fraction * 100)}%")
            if self._status_label is not None:
                self._status_label.set_label(self._t(message_key))
            return False

        self._glib.idle_add(_apply)

    @staticmethod
    def _run_stage_with_timeout(worker: Callable[[], None], timeout_sec: float) -> None:
        executor = ThreadPoolExecutor(max_workers=1)
        future = executor.submit(worker)
        try:
            future.result(timeout=timeout_sec)
        except FuturesTimeoutError:
            pass
        except Exception:
            pass
        finally:
            executor.shutdown(wait=False, cancel_futures=True)

    def _run_startup_stages(self) -> None:
        stages: list[tuple[str, Callable[[], None]]] = [
            ("splash.stage.pairing", self._stage_pairing),
            ("splash.stage.grants", self._stage_grants),
            ("splash.stage.device_scan", self._stage_device_scan),
            ("splash.stage.saas", self._stage_saas),
        ]
        total = len(stages)
        deadline = threading.Timer(TOTAL_STARTUP_TIMEOUT_SEC, self._glib.idle_add, args=(self._finish,))
        deadline.daemon = True
        deadline.start()
        try:
            for index, (message_key, worker) in enumerate(stages, start=1):
                self._set_stage((index - 1) / total, message_key)
                self._run_stage_with_timeout(worker, STAGE_TIMEOUT_SEC)
                self._set_stage(index / total, message_key)
        finally:
            deadline.cancel()
        self._glib.idle_add(self._finish)

    def _stage_pairing(self) -> None:
        self._adapter.read_dashboard_snapshot()

    def _stage_grants(self) -> None:
        self._adapter.read_capability_snapshot()

    def _stage_device_scan(self) -> None:
        self._adapter.ensure_startup_device_scan(force=True)

    def _stage_saas(self) -> None:
        self._adapter.fetch_saas_context(force=True)
        self._adapter.fetch_owner_profile(force=True)

    def _finish(self) -> bool:
        global _active_splash_controller
        with self._finish_lock:
            if self._finished:
                return False
            self._finished = True
        if self._window is not None:
            try:
                self._window.close()
            except Exception:
                pass
            self._window = None
        if _active_splash_controller is self:
            _active_splash_controller = None
        if self._on_ready is not None:
            self._on_ready()
        return False

    def destroy(self) -> None:
        """Dismiss splash immediately (idempotent)."""
        self._glib.idle_add(self._finish)
