#!/usr/bin/env python3
"""OAuth-Hilfsserver für die Busch-Radio Spotify Bridge.

Stellt unter http://<ha-ip>:5589 eine Hilfsseite bereit,
die den einmaligen Spotify-Autorisierungsprozess vereinfacht.

Endpoints:
  GET /          -> HTML-Hilfsseite
  GET /auth-url  -> JSON: {"url": "https://accounts.spotify.com/..."}
  GET /status    -> JSON: {"authed": true/false}
"""
import http.server
import json
import os
import sys
import urllib.parse

HA_IP = sys.argv[1] if len(sys.argv) > 1 else "homeassistant.local"
AUTH_URL_FILE = "/tmp/busch-radio/auth_url.txt"
CRED_FILE = "/data/librespot-cache/credentials.json"

HTML = f"""<!DOCTYPE html>
<html lang="de">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Busch-Radio – Spotify-Anmeldung</title>
  <style>
    * {{ box-sizing: border-box; margin: 0; padding: 0; }}
    body {{
      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
      background: #1a1a2e;
      color: #e0e0e0;
      min-height: 100vh;
      padding: 16px;
      display: flex;
      flex-direction: column;
      align-items: center;
    }}
    .card {{
      background: #16213e;
      border-radius: 12px;
      padding: 20px 24px;
      max-width: 620px;
      width: 100%;
      margin: 10px 0;
      border: 1px solid #0f3460;
    }}
    h1 {{ color: #1db954; font-size: 1.4em; margin-bottom: 6px; }}
    h2 {{
      color: #8a9bb0;
      font-size: 0.8em;
      text-transform: uppercase;
      letter-spacing: 0.08em;
      margin-bottom: 14px;
    }}
    .step {{
      display: flex;
      gap: 14px;
      align-items: flex-start;
      margin: 10px 0;
      padding: 14px;
      background: #0f3460;
      border-radius: 8px;
    }}
    .num {{
      background: #1db954;
      color: #000;
      border-radius: 50%;
      width: 26px; height: 26px;
      min-width: 26px;
      display: flex;
      align-items: center;
      justify-content: center;
      font-weight: 700;
      font-size: 0.85em;
    }}
    .body {{ flex: 1; }}
    p {{ margin: 5px 0; line-height: 1.55; font-size: 0.93em; }}
    code {{
      background: #1a1a2e;
      padding: 2px 6px;
      border-radius: 4px;
      color: #f0a500;
      font-size: 0.88em;
      word-break: break-all;
    }}
    .btn {{
      display: inline-block;
      background: #1db954;
      color: #000 !important;
      padding: 9px 20px;
      border-radius: 20px;
      font-weight: 700;
      font-size: 0.9em;
      cursor: pointer;
      border: none;
      text-decoration: none;
      margin-top: 10px;
    }}
    .btn:hover {{ background: #17a349; }}
    input[type=text] {{
      width: 100%;
      padding: 9px 12px;
      border-radius: 6px;
      border: 1px solid #264070;
      background: #1a1a2e;
      color: #e0e0e0;
      font-size: 0.88em;
      margin-top: 8px;
    }}
    .spinner {{
      display: inline-block;
      width: 14px; height: 14px;
      border: 2px solid #333;
      border-top-color: #1db954;
      border-radius: 50%;
      animation: spin 0.8s linear infinite;
      vertical-align: middle;
      margin-left: 6px;
    }}
    @keyframes spin {{ to {{ transform: rotate(360deg); }} }}
    .ok {{ color: #1db954; }}
    .warn {{ color: #f0a500; }}
    .err {{ color: #e05050; font-size: 0.85em; margin-top: 6px; display: none; }}
    .hint {{ color: #8a9bb0; font-size: 0.83em; margin-top: 5px; }}
    .hidden {{ display: none !important; }}
    .authed-banner {{
      background: #0b3d1f;
      border: 1px solid #1db954;
      border-radius: 8px;
      padding: 14px;
      text-align: center;
      display: none;
    }}
  </style>
</head>
<body>
  <div class="card">
    <h1>&#127925; Busch-Radio &ndash; Spotify-Anmeldung</h1>
    <p class="hint">Einmaliger Einrichtungs-Assistent &bull; Credentials werden dauerhaft gespeichert.</p>
    <div class="authed-banner" id="authed-banner">
      <span class="ok">&#10003; Bereits autorisiert &ndash; keine erneute Anmeldung n&ouml;tig.</span>
    </div>
  </div>

  <div class="card">
    <h2>Schritt 1 &ndash; Spotify-Anmeldung starten</h2>
    <div class="step">
      <div class="num">1</div>
      <div class="body">
        <p>Klicke auf den Link, um die Spotify-Autorisierung zu &ouml;ffnen.</p>
        <div id="auth-waiting">
          <p class="warn">Warte auf librespot&hellip;<span class="spinner"></span></p>
        </div>
        <div id="auth-ready" class="hidden">
          <a id="auth-link" href="#" target="_blank" class="btn">Mit Spotify anmelden &rarr;</a>
        </div>
        <p class="hint">Du ben&ouml;tigst ein Spotify-Premium-Konto.</p>
      </div>
    </div>
    <div class="step">
      <div class="num">2</div>
      <div class="body">
        <p>Melde dich mit deinem Spotify-Konto an und best&auml;tige die Berechtigungsanfrage.</p>
      </div>
    </div>
  </div>

  <div class="card">
    <h2>Schritt 2 &ndash; Weiterleitung abschlie&szlig;en</h2>
    <div class="step">
      <div class="num">3</div>
      <div class="body">
        <p>Nach der Anmeldung leitet Spotify auf eine Seite weiter, die nicht erreichbar ist:</p>
        <p><code>http://127.0.0.1:5588/login?code=&hellip;</code></p>
        <p>Kopiere diese URL vollst&auml;ndig aus der Adressleiste.</p>
      </div>
    </div>
    <div class="step">
      <div class="num">4</div>
      <div class="body">
        <p>F&uuml;ge die kopierte URL hier ein und klicke auf &bdquo;Weiter&ldquo;:</p>
        <input type="text" id="url-input" placeholder="http://127.0.0.1:5588/login?code=...">
        <p id="url-err" class="err">Bitte eine g&uuml;ltige URL einf&uuml;gen (beginnt mit <code>http://127.0.0.1:5588</code>).</p>
        <button class="btn" onclick="fixUrl()">Weiter &rarr;</button>
      </div>
    </div>
    <div class="step">
      <div class="num">5</div>
      <div class="body">
        <p>Im neu ge&ouml;ffneten Tab erscheint: <span class="ok">Autorisierung erfolgreich!</span></p>
        <p>Das Add-on startet danach automatisch durch. Diese Seite kann geschlossen werden.</p>
      </div>
    </div>
  </div>

  <script>
    const HA_IP = "{HA_IP}";

    async function checkAuthUrl() {{
      try {{
        const r = await fetch('/auth-url');
        const d = await r.json();
        if (d.url) {{
          document.getElementById('auth-waiting').classList.add('hidden');
          document.getElementById('auth-link').href = d.url;
          document.getElementById('auth-ready').classList.remove('hidden');
        }} else {{
          setTimeout(checkAuthUrl, 2000);
        }}
      }} catch(e) {{
        setTimeout(checkAuthUrl, 2000);
      }}
    }}

    async function checkAuthed() {{
      try {{
        const r = await fetch('/status');
        const d = await r.json();
        if (d.authed) {{
          document.getElementById('authed-banner').style.display = 'block';
        }}
      }} catch(e) {{}}
    }}

    function fixUrl() {{
      const raw = document.getElementById('url-input').value.trim();
      const err = document.getElementById('url-err');
      if (!raw.startsWith('http://127.0.0.1:5588')) {{
        err.style.display = 'block';
        return;
      }}
      err.style.display = 'none';
      window.open(raw.replace('127.0.0.1', HA_IP), '_blank');
    }}

    document.getElementById('url-input').addEventListener('keydown', function(e) {{
      if (e.key === 'Enter') fixUrl();
    }});

    checkAuthUrl();
    checkAuthed();
  </script>
</body>
</html>
"""


class Handler(http.server.BaseHTTPRequestHandler):
    def log_message(self, *args):
        pass

    def do_GET(self):
        path = urllib.parse.urlparse(self.path).path

        if path == "/auth-url":
            url = None
            if os.path.exists(AUTH_URL_FILE):
                with open(AUTH_URL_FILE) as f:
                    url = f.read().strip() or None
            body = json.dumps({"url": url}).encode()
            self._respond(200, "application/json", body)

        elif path == "/status":
            body = json.dumps({"authed": os.path.exists(CRED_FILE)}).encode()
            self._respond(200, "application/json", body)

        else:
            body = HTML.encode()
            self._respond(200, "text/html; charset=utf-8", body)

    def _respond(self, code, content_type, body):
        self.send_response(code)
        self.send_header("Content-Type", content_type)
        self.send_header("Content-Length", str(len(body)))
        self.end_headers()
        self.wfile.write(body)


if __name__ == "__main__":
    server = http.server.HTTPServer(("0.0.0.0", 5589), Handler)
    server.serve_forever()
