"""PilotNG.exe — natives Fenster + Vollstart wie "TibiaPilotNG Bot".

Startet KEINE eigene Logik nach, sondern loest exakt dieselbe geplante
Aufgabe aus wie die Verknuepfung "TibiaPilotNG Bot"
(TibiaPilotNG-OneClick -> tools/Start-PilotNG-OneClick.ps1). Damit ist
das Startverhalten garantiert identisch: HID pruefen, Bildschirm
vorbereiten, OBS, Tibia-Profil, Client, Login, Bot.

Bis der Bot-Server antwortet, zeigt das Fenster einen Startbildschirm
mit dem echten Fortschritt aus .one-click.log — kein "es passiert
nichts" mehr.
"""
import json
import os
import subprocess
import sys
import threading
import time
import urllib.request
from pathlib import Path

URL = 'http://127.0.0.1:8620'
TASK_ONECLICK = 'TibiaPilotNG-OneClick'
NO_WINDOW = 0x08000000  # CREATE_NO_WINDOW

# Rohstatus aus .one-click.log -> Klartext fuer den Startbildschirm.
STATUS_TEXT = {
    'start': 'Startvorgang läuft …',
    'arduino-flash': 'Arduino wird programmiert …',
    'hid-ready': 'Eingabe-Hardware bereit',
    'obs-start': 'OBS wird gestartet …',
    'client-launch': 'Tibia-Client wird gestartet …',
    'obs-projector': 'Bildschirm-Aufnahme wird eingerichtet …',
    'bot-start': 'Bot wird gestartet …',
    'running': 'Läuft — Oberfläche wird geladen …',
    'normal-profile-restored': 'Beendet — Profil zurückgesetzt.',
}


def findRepo():
    """Repo-Wurzel finden (funktioniert eingefroren und als Skript)."""
    configured = os.environ.get('PILOTNG_REPO')
    if configured and (Path(configured) / 'main.py').exists():
        return Path(configured)
    base = Path(sys.executable if getattr(sys, 'frozen', False) else __file__)
    for parent in [base, *base.parents]:
        if (parent / 'main.py').exists() and (parent / 'webui').exists():
            return parent
    return Path(os.environ.get('USERPROFILE', 'C:/Users/Privat')) / 'TibiaPilotNG'


REPO = findRepo()


def cleanEnv():
    """Env ohne PyInstaller-Reste — sonst erben Kindprozesse Muell."""
    env = dict(os.environ)
    for key in ('_MEIPASS2', '_PYI_ARCHIVE_FILE', '_PYI_APPLICATION_HOME_DIR',
                'PYTHONHOME', 'PYTHONPATH'):
        env.pop(key, None)
    meipass = getattr(sys, '_MEIPASS', None)
    if meipass and env.get('PATH', '').startswith(meipass):
        env['PATH'] = env['PATH'][len(meipass):].lstrip(os.pathsep)
    return env


def serverAlive():
    try:
        with urllib.request.urlopen(URL + '/api/state', timeout=1):
            return True
    except OSError:
        return False


def startOneClick():
    """Exakt der Weg der Verknuepfung "TibiaPilotNG Bot"."""
    return subprocess.run(
        ['schtasks', '/Run', '/TN', TASK_ONECLICK],
        creationflags=NO_WINDOW, capture_output=True, check=False,
        env=cleanEnv(),
    ).returncode == 0


def readTextFile(path):
    """PowerShell schreibt mal UTF-8 (mit BOM), mal ANSI — beides lesen."""
    try:
        raw = Path(path).read_bytes()
    except OSError:
        return None
    for encoding in ('utf-8-sig', 'cp1252'):
        try:
            return raw.decode(encoding)
        except UnicodeDecodeError:
            continue
    return raw.decode('utf-8', errors='replace')


def startupStatus():
    """(Text, istFehler) aus .one-click.log / .one-click-result.json."""
    raw = readTextFile(REPO / '.one-click-result.json')
    if raw:
        try:
            result = json.loads(raw)
            if not result.get('ok', True):
                return result.get('message', 'Start fehlgeschlagen.'), True
        except ValueError:
            pass
    text = readTextFile(REPO / '.one-click.log')
    if text is None:
        return 'Startvorgang läuft …', False
    lines = [line for line in text.splitlines() if line.strip()]
    if not lines:
        return 'Startvorgang läuft …', False
    status = lines[-1].split(' ', 1)[-1].strip()
    if status.startswith('error='):
        return status[6:], True
    return STATUS_TEXT.get(status, status), False


SPLASH = """<!DOCTYPE html><html lang="de"><head><meta charset="utf-8">
<style>
*{margin:0;padding:0;box-sizing:border-box;font-family:'Segoe UI',system-ui,sans-serif}
body{height:100vh;display:grid;place-items:center;color:#eef2f9;overflow:hidden;
 background:linear-gradient(155deg,#070b14 0%,#0b1322 48%,#080b16 100%)}
.blob{position:fixed;border-radius:50%;filter:blur(90px);opacity:.5;animation:drift 26s ease-in-out infinite alternate}
.b1{width:60vw;height:60vw;left:-18vw;top:-24vw;background:radial-gradient(circle,rgba(227,58,99,.85),transparent 65%)}
.b2{width:55vw;height:55vw;right:-10vw;top:-8vw;background:radial-gradient(circle,rgba(59,130,246,.55),transparent 65%);animation-delay:-8s}
@keyframes drift{from{transform:translate3d(0,0,0) scale(1)}to{transform:translate3d(-4vw,6vh,0) scale(1.1)}}
.card{position:relative;z-index:1;width:min(560px,86vw);padding:38px 40px;border-radius:26px;text-align:center;
 background:linear-gradient(160deg,rgba(255,255,255,.07),transparent 45%),rgba(148,170,210,.08);
 backdrop-filter:blur(26px) saturate(1.6);-webkit-backdrop-filter:blur(26px) saturate(1.6);
 border:1px solid rgba(255,255,255,.16);box-shadow:0 30px 70px -20px rgba(3,7,16,.6)}
.logo{font-size:24px;font-weight:700;letter-spacing:4px;
 background:linear-gradient(120deg,#eef2f9 30%,#e33a63);-webkit-background-clip:text;
 background-clip:text;-webkit-text-fill-color:transparent}
.sub{font-size:12px;color:#8b98ad;margin-top:4px;letter-spacing:.4px}
.ring{width:52px;height:52px;margin:26px auto 18px;border-radius:50%;
 border:3px solid rgba(255,255,255,.12);border-top-color:#e33a63;animation:spin 1s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}
#msg{font-size:14.5px;font-weight:600;line-height:1.6;min-height:44px;overflow-wrap:anywhere}
#msg.err{color:#f87171}
#hint{font-size:12px;color:#63708a;margin-top:12px;line-height:1.6;overflow-wrap:anywhere}
.err-ring{border-top-color:#f87171;animation:none}
</style></head><body>
<div class="blob b1"></div><div class="blob b2"></div>
<div class="card">
  <div class="logo">PILOT NG</div><div class="sub">Tibia Automation</div>
  <div class="ring" id="ring"></div>
  <div id="msg">Startvorgang läuft …</div>
  <div id="hint"></div>
</div>
<script>
window.setStatus = (text, isError, hint) => {
  const m = document.getElementById('msg');
  m.textContent = text; m.className = isError ? 'err' : '';
  document.getElementById('ring').className = isError ? 'ring err-ring' : 'ring';
  document.getElementById('hint').textContent = hint || '';
};
</script></body></html>"""


def main():
    import webview

    window = webview.create_window(
        'PilotNG', html=SPLASH, width=1420, height=920,
        min_size=(1000, 700), background_color='#070b14',
    )

    def bootstrap():
        # Laeuft schon ein Bot mit Server? Dann direkt rein.
        if serverAlive():
            window.load_url(URL)
            return
        if not startOneClick():
            window.evaluate_js(
                "setStatus('Die Startaufgabe \\'%s\\' wurde nicht gefunden.',"
                " true, 'Bitte tools\\\\Install-PilotNG-OneClick.ps1 einmal"
                " ausfuehren.')" % TASK_ONECLICK)
            return
        lastText = None
        deadline = time.time() + 900  # bis zu 15 min (Login/Client dauern)
        while time.time() < deadline:
            if serverAlive():
                window.load_url(URL)
                return
            text, isError = startupStatus()
            if text != lastText:
                lastText = text
                hint = ('Du kannst dieses Fenster offen lassen — '
                        'es wechselt automatisch zur Oberfläche.'
                        if not isError else
                        'Beheb den Punkt und starte PilotNG erneut.')
                # json.dumps schuetzt vor Anfuehrungszeichen/Umlauten.
                window.evaluate_js('setStatus(%s, %s, %s)' % (
                    json.dumps(text), 'true' if isError else 'false',
                    json.dumps(hint)))
            if isError:
                return  # Fehler stehen lassen, nicht weiterpollen
            time.sleep(1)
        window.evaluate_js(
            "setStatus('Zeitüberschreitung beim Start.', true,"
            " 'Details stehen in .one-click.log im PilotNG-Ordner.')")

    threading.Thread(target=bootstrap, daemon=True).start()
    webview.start()
    # Fenster zu = nur das Fenster. Der Bot laeuft weiter wie beim
    # Shortcut "TibiaPilotNG Bot" und raeumt selbst auf, wenn Tibia endet.
    # Eigenen Prozessbaum mitnehmen, sonst bleiben WebView2-Kinder haengen.
    subprocess.run(
        ['taskkill', '/PID', str(os.getpid()), '/T', '/F'],
        creationflags=NO_WINDOW, capture_output=True, check=False,
    )
    os._exit(0)


if __name__ == '__main__':
    main()
