#!/usr/bin/env python3
"""Jam – lila Desktop-Monster-Begleiter."""

from __future__ import annotations

import sys
import traceback
from pathlib import Path

LOG_FILE = Path(__file__).resolve().parent / "data" / "jam-crash.log"


def _log_crash(msg: str) -> None:
    try:
        LOG_FILE.parent.mkdir(parents=True, exist_ok=True)
        LOG_FILE.write_text(msg, encoding="utf-8")
    except OSError:
        pass


def main() -> int:
    try:
        from PyQt6.QtCore import QTimer
        from PyQt6.QtWidgets import QApplication

        from jam.brain import JamBrain
        from jam.listener import start_listener
        from jam.single_instance import (
            bind_singleton_server,
            claim_singleton,
            request_existing_window,
        )
        from jam.window import JamWindow

        if not claim_singleton():
            request_existing_window()
            return 0

        import traceback as _tb

        from jam.crash_guard import log_crash

        def _excepthook(exc_type, exc, tb_obj) -> None:
            log_crash("".join(_tb.format_exception(exc_type, exc, tb_obj)))
            sys.__excepthook__(exc_type, exc, tb_obj)

        sys.excepthook = _excepthook

        app = QApplication(sys.argv)
        app.setApplicationName("Jam")
        # Jam bleibt auch wenn Feuerwerk-/Partikel-Fenster zu sind (nicht beenden).
        app.setQuitOnLastWindowClosed(False)

        brain = JamBrain()
        brain.state.tick_age()

        from jam.crash_guard import log_crash, safe_call

        def _boot(step: str, fn) -> None:
            safe_call(lambda: fn(brain), label=f"startup:{step}")

        from jam.always_on import apply_always_on_startup
        from jam.keep_awake import apply_on_startup
        from jam.max_earn import apply_max_earn_startup
        from jam.active_sell import apply_active_sell_startup
        from jam.world_earn import apply_world_earn_startup
        from jam.stream_prep import apply_stream_on_startup
        from jam.delegate_mode import apply_delegate_startup

        _boot("keep_awake", apply_on_startup)
        from jam.resource_budget import apply_memory_budget_startup

        _boot("memory_budget", apply_memory_budget_startup)
        _boot("always_on", apply_always_on_startup)
        _boot("max_earn", apply_max_earn_startup)
        _boot("world_earn", apply_world_earn_startup)
        _boot("active_sell", apply_active_sell_startup)
        from jam.sell_focus import apply_startup as apply_sell_focus_startup

        _boot("sell_focus", apply_sell_focus_startup)
        _boot("stream_prep", apply_stream_on_startup)
        if __import__("os").environ.get("JAM_DELEGATE", "").strip() in ("1", "true", "yes"):
            from jam.delegate_mode import enable_delegate_mode

            enable_delegate_mode(brain, remember_grant=True)
        _boot("delegate", apply_delegate_startup)
        brain.save()

        win = JamWindow(brain)
        win.setWindowOpacity(1.0)

        def _focus_jam() -> None:
            win.show()
            win.raise_()
            win.activateWindow()

        singleton = bind_singleton_server(_focus_jam)
        if singleton is None and request_existing_window():
            return 0
        if singleton is not None:
            app._jam_singleton = singleton

        _focus_jam()
        QTimer.singleShot(500, _focus_jam)

        def on_wake(text: str) -> None:
            win.wake_requested.emit(text)

        def on_mic_err(msg: str) -> None:
            win.bubble.emit(f"Mikro: {msg}")

        start_listener(on_wake, on_mic_err)

        return app.exec()
    except Exception:
        _log_crash(traceback.format_exc())
        raise


if __name__ == "__main__":
    raise SystemExit(main())
