"""
PyInstaller Runtime Hook for Kiwy Signage Player
------------------------------------------------
Runs at startup of the packaged .exe to fix paths and environment.
Creates all necessary folders LOCAL to the executable's directory.
"""

import os
import sys
import platform
from pathlib import Path

# ── IMPORTANT: Set Windows environment BEFORE any Kivy code runs ──
# This must happen before main.py's top-level code executes, because
# main.py sets SDL_VIDEODRIVER=wayland,x11,dummy which would crash on Windows.
os.environ['SDL_VIDEODRIVER'] = 'windows'
os.environ['SDL_AUDIODRIVER'] = 'directsound'
os.environ['KIVY_WINDOW'] = 'sdl2'
os.environ['KIVY_GL_BACKEND'] = 'angle_sdl2'
os.environ['KIVY_VIDEO'] = 'ffpyplayer'
os.environ['KIVY_AUDIO'] = 'ffpyplayer'
os.environ['FFPYPLAYER_CODECS'] = 'h264,h265,vp9,vp8'
os.environ['SDL_VIDEO_ALLOW_SCREENSAVER'] = '0'
os.environ['KIVY_NO_FILELOG'] = '1'
os.environ['KIVY_INPUTPROVIDERS'] = ''  # Let Kivy auto-detect on Windows

# ── Capture ALL early output to a crash log ─────────────────────────
# Ensure we catch any exception that happens before Logger is available.
_startup_log_path = None
try:
    _exe_dir = Path(sys.executable).parent
    _startup_log_path = _exe_dir / 'logs' / 'startup_crash.log'
    (_startup_log_path.parent).mkdir(parents=True, exist_ok=True)
    with open(_startup_log_path, 'w') as _f:
        _f.write("pyi_runtime_hook.py started\n")
except Exception:
    pass


def _setup_paths():
    """Ensure the app can find its bundled files at runtime.

    All data folders (config, media, playlists, logs) are created
    LOCAL to the executable's directory — NOT in %%APPDATA%%.
    """
    # In PyInstaller, sys.executable is the .exe path.
    # sys._MEIPASS is the extraction directory (i.e. _internal/ folder).
    exe_dir = Path(sys.executable).parent
    internal_dir = Path(getattr(sys, '_MEIPASS', exe_dir))

    # ── Change cwd to _internal so Builder.load_file('signage_player.kv')
    #    and other relative file references from main.py resolve ─────
    os.chdir(str(internal_dir))

    # Add bundled src directory to Python path
    src_dir = str(internal_dir / 'src')
    if os.path.isdir(src_dir) and src_dir not in sys.path:
        sys.path.insert(0, src_dir)

    # Add internal directory for config/media/playlists access
    if str(internal_dir) not in sys.path:
        sys.path.insert(0, str(internal_dir))

    # ── Local folders next to the .exe ──────────────────────────────
    # All data lives in the SAME folder as the executable so the user
    # can copy/move the whole directory and everything still works.
    os.environ['KIWY_DATA_DIR'] = str(exe_dir)

    # Set KIVY_HOME to a local .kivy folder next to the .exe
    kivy_home = exe_dir / '.kivy'
    os.environ.setdefault('KIVY_HOME', str(kivy_home))
    kivy_home.mkdir(parents=True, exist_ok=True)

    # Create local data folders next to the .exe
    for sub in ['config', 'config/resources', 'media', 'playlists', 'logs']:
        (exe_dir / sub).mkdir(parents=True, exist_ok=True)


def _copy_bundled_resources():
    """Copy bundled resource/config files to the local folders on first run."""
    exe_dir = Path(sys.executable).parent
    internal_dir = Path(getattr(sys, '_MEIPASS', exe_dir))

    # Files to copy (source in bundle -> destination next to .exe)
    files_to_copy = [
        ('config/app_config.json', 'config/app_config.json'),
        ('config/resources/access-card.png', 'config/resources/access-card.png'),
        ('config/resources/arrow.png', 'config/resources/arrow.png'),
        ('config/resources/backward.png', 'config/resources/backward.png'),
        ('config/resources/card-checked.png', 'config/resources/card-checked.png'),
        ('config/resources/edit-pen.png', 'config/resources/edit-pen.png'),
        ('config/resources/exit.png', 'config/resources/exit.png'),
        ('config/resources/forward.png', 'config/resources/forward.png'),
        ('config/resources/intro1.mp4', 'config/resources/intro1.mp4'),
        ('config/resources/pause.png', 'config/resources/pause.png'),
        ('config/resources/pencil.png', 'config/resources/pencil.png'),
        ('config/resources/play.png', 'config/resources/play.png'),
        ('config/resources/settings.png', 'config/resources/settings.png'),
    ]

    for src_rel, dest_rel in files_to_copy:
        src_path = internal_dir / src_rel
        dest_path = exe_dir / dest_rel
        if src_path.is_file() and not dest_path.exists():
            try:
                dest_path.parent.mkdir(parents=True, exist_ok=True)
                import shutil
                shutil.copy2(str(src_path), str(dest_path))
            except Exception:
                pass  # Non-critical; app can still run


# ── Wrap everything in try/except to capture early crashes ──────────
try:
    _setup_paths()
    _copy_bundled_resources()
    # If we reach here, the hook finished successfully
    try:
        with open(_startup_log_path, 'a') as _f:
            _f.write("pyi_runtime_hook.py completed successfully\n")
    except Exception:
        pass
except Exception as _hook_exc:
    import traceback as _tb
    try:
        with open(_startup_log_path, 'a') as _f:
            _f.write(f"pyi_runtime_hook.py CRASHED: {_hook_exc}\n")
            _tb.print_exc(file=_f)
    except Exception:
        pass
    raise  # Re-raise so the .exe still fails visibly
