"""Runtime helpers for console-less Windows launches."""

from __future__ import annotations

import sys
import traceback
from datetime import datetime
from pathlib import Path
from typing import Callable, TypeVar


BASE_DIR = Path(__file__).resolve().parent
FATAL_LOG = BASE_DIR / "warehouse_fatal.log"
_STDIO_HANDLES = []
T = TypeVar("T")


def ensure_stdio(app_name: str) -> None:
    """Give ``pythonw`` a real stdout/stderr target before loggers are imported."""

    stamp = datetime.now().strftime("%Y%m%d")
    if sys.stdout is None:
        handle = (BASE_DIR / f"{app_name}_stdout_{stamp}.log").open("a", encoding="utf-8", buffering=1)
        _STDIO_HANDLES.append(handle)
        sys.stdout = handle
    if sys.stderr is None:
        handle = (BASE_DIR / f"{app_name}_stderr_{stamp}.log").open("a", encoding="utf-8", buffering=1)
        _STDIO_HANDLES.append(handle)
        sys.stderr = handle


def log_fatal(app_name: str, exc: BaseException) -> None:
    """Write one startup/runtime crash to a persistent log file."""

    with FATAL_LOG.open("a", encoding="utf-8") as handle:
        handle.write("\n" + "=" * 80 + "\n")
        handle.write(f"{datetime.now():%Y-%m-%d %H:%M:%S} | {app_name}\n")
        handle.write("".join(traceback.format_exception(type(exc), exc, exc.__traceback__)))


def show_fatal_message(app_name: str, exc: BaseException) -> None:
    """Show a best-effort message box for console-less launches."""

    try:
        import tkinter as tk
        from tkinter import messagebox

        root = tk.Tk()
        root.withdraw()
        messagebox.showerror(
            app_name,
            f"Avvio non riuscito.\n\nDettaglio salvato in:\n{FATAL_LOG}\n\n{exc}",
            parent=root,
        )
        root.destroy()
    except Exception:
        pass


def run_with_fatal_log(app_name: str, func: Callable[[], T]) -> T:
    """Run an app entry point and persist otherwise invisible ``pythonw`` crashes."""

    try:
        return func()
    except BaseException as exc:
        log_fatal(app_name, exc)
        show_fatal_message(app_name, exc)
        raise
