#!/usr/bin/env python3
"""Minimal HTTPS-behind-Tailscale server for privacy policy and one-time WHOOP setup."""
from __future__ import annotations

import html
import json
import os
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from pathlib import Path
from urllib.parse import parse_qs

HOST = "127.0.0.1"
PORT = 8765
POLICY = Path("/home/sheridan/health_public/privacy-policy.html")
CONFIG_DIR = Path("/home/sheridan/.config/sheridan-health")
TOKEN_FILE = CONFIG_DIR / "whoop_setup_token"
CREDENTIAL_FILE = CONFIG_DIR / "whoop_client.json"
REDIRECT_URI = "whoop://sheridan-health/callback"

FORM = """<!doctype html><html lang='en'><head><meta charset='utf-8'>
<meta name='viewport' content='width=device-width,initial-scale=1'>
<title>Secure WHOOP Setup</title><style>
body{font:16px/1.5 Arial,sans-serif;background:#f5f7f8;color:#17212b;margin:0}
main{max-width:560px;margin:40px auto;background:#fff;border:1px solid #dfe5ea;border-radius:12px;padding:36px}
label{display:block;margin:18px 0 6px;font-weight:700}input{width:100%;padding:12px;border:1px solid #aab4bc;border-radius:7px;font-size:16px;box-sizing:border-box}
button{margin-top:24px;padding:12px 18px;background:#145c78;color:#fff;border:0;border-radius:7px;font-weight:700;font-size:16px}
.note{color:#5b6773}code{background:#eef2f4;padding:2px 5px;border-radius:4px}@media(max-width:650px){main{margin:0;border:0;border-radius:0;padding:24px}}
</style></head><body><main><h1>Secure WHOOP connection</h1>
<p>Enter the Client ID and Client Secret shown in the WHOOP Developer Dashboard.</p>
<p class='note'>The values are sent over HTTPS directly to Sheridan's Hermes server, saved in an owner-only local file, and never placed in chat or Google Sheets. This page disables itself after one successful submission.</p>
<form method='post' autocomplete='off'>
<label for='client_id'>Client ID</label><input id='client_id' name='client_id' required autocapitalize='off' spellcheck='false'>
<label for='client_secret'>Client Secret</label><input id='client_secret' name='client_secret' type='password' required autocapitalize='off' spellcheck='false'>
<p class='note'>Redirect URI: <code>whoop://sheridan-health/callback</code></p>
<button type='submit'>Save credentials securely</button></form></main></body></html>"""

SUCCESS = """<!doctype html><html><head><meta charset='utf-8'><meta name='viewport' content='width=device-width,initial-scale=1'><title>WHOOP setup complete</title></head><body style='font:18px/1.5 Arial,sans-serif;max-width:620px;margin:50px auto;padding:20px'><h1>Credentials saved securely</h1><p>This one-time setup page is now disabled. Return to Hermes chat and say <strong>credentials saved</strong>.</p></body></html>"""

class Handler(BaseHTTPRequestHandler):
    server_version = "SheridanHealth/1.0"

    def _headers(self, status: int, content_type: str = "text/html; charset=utf-8") -> None:
        self.send_response(status)
        self.send_header("Content-Type", content_type)
        self.send_header("Cache-Control", "no-store")
        self.send_header("X-Content-Type-Options", "nosniff")
        self.send_header("X-Frame-Options", "DENY")
        self.send_header("Referrer-Policy", "no-referrer")
        self.send_header("Content-Security-Policy", "default-src 'none'; style-src 'unsafe-inline'; form-action 'self'; base-uri 'none'; frame-ancestors 'none'")
        self.end_headers()

    def _active_token(self) -> str | None:
        try:
            return TOKEN_FILE.read_text(encoding="utf-8").strip()
        except FileNotFoundError:
            return None

    def _is_setup_path(self) -> bool:
        token = self._active_token()
        return bool(token and self.path == f"/whoop-setup/{token}")

    def do_GET(self) -> None:
        if self.path in ("/", "/privacy-policy.html"):
            self._headers(200)
            self.wfile.write(POLICY.read_bytes())
            return
        if self._is_setup_path():
            self._headers(200)
            self.wfile.write(FORM.encode())
            return
        self._headers(404, "text/plain; charset=utf-8")
        self.wfile.write(b"Not found")

    def do_POST(self) -> None:
        if not self._is_setup_path():
            self._headers(404, "text/plain; charset=utf-8")
            self.wfile.write(b"Not found")
            return
        try:
            length = int(self.headers.get("Content-Length", "0"))
        except ValueError:
            length = 0
        if length < 1 or length > 16384:
            self._headers(400, "text/plain; charset=utf-8")
            self.wfile.write(b"Invalid request")
            return
        values = parse_qs(self.rfile.read(length).decode("utf-8"), keep_blank_values=True)
        client_id = values.get("client_id", [""])[0].strip()
        client_secret = values.get("client_secret", [""])[0].strip()
        if not client_id or not client_secret:
            self._headers(400)
            self.wfile.write(b"<h1>Both values are required.</h1>")
            return
        CONFIG_DIR.mkdir(parents=True, exist_ok=True)
        os.chmod(CONFIG_DIR, 0o700)
        temp = CREDENTIAL_FILE.with_suffix(".tmp")
        temp.write_text(json.dumps({"client_id": client_id, "client_secret": client_secret, "redirect_uri": REDIRECT_URI}, indent=2) + "\n", encoding="utf-8")
        os.chmod(temp, 0o600)
        temp.replace(CREDENTIAL_FILE)
        os.chmod(CREDENTIAL_FILE, 0o600)
        TOKEN_FILE.unlink(missing_ok=True)
        self._headers(200)
        self.wfile.write(SUCCESS.encode())

    def log_message(self, fmt: str, *args: object) -> None:
        safe_path = "/whoop-setup/[REDACTED]" if self.path.startswith("/whoop-setup/") else self.path
        print(f"{self.client_address[0]} {self.command} {safe_path}", flush=True)

if __name__ == "__main__":
    ThreadingHTTPServer((HOST, PORT), Handler).serve_forever()
