#!/usr/bin/env python3
"""Sample RP: PKCE against sandbox or a local mock IdP; print sub + RSI handle.

Usage:
  python3 print_me.py --mock
  python3 print_me.py --issuer https://id-dev.navcom.ai --client-id … --code … --verifier …
Never commit tokens.
"""
from __future__ import annotations

import argparse
import json
import os
import sys
from http.server import BaseHTTPRequestHandler, HTTPServer
from urllib.parse import parse_qs, urlparse

sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "python"))
from navcom_oauth import NavcomClient, pkce_s256  # noqa: E402


class MockIdP(BaseHTTPRequestHandler):
    def log_message(self, *args):
        return

    def do_GET(self):
        parsed = urlparse(self.path)
        if parsed.path == "/oauth/v1/me":
            auth = self.headers.get("Authorization") or ""
            if not auth.startswith("Bearer "):
                self.send_error(401)
                return
            body = json.dumps({"sub": "42", "rsi_handle": "Yuka", "name": "Yuka"}).encode()
            self.send_response(200)
            self.send_header("Content-Type", "application/json")
            self.send_header("Content-Length", str(len(body)))
            self.end_headers()
            self.wfile.write(body)
            return
        self.send_error(404)

    def do_POST(self):
        parsed = urlparse(self.path)
        length = int(self.headers.get("Content-Length") or 0)
        raw = self.rfile.read(length).decode()
        form = {k: v[0] for k, v in parse_qs(raw).items()}
        if parsed.path == "/oauth/token":
            if form.get("grant_type") != "authorization_code":
                self.send_error(400)
                return
            if not form.get("code_verifier"):
                self.send_error(400)
                return
            body = json.dumps({"access_token": "mock-access", "token_type": "Bearer"}).encode()
            self.send_response(200)
            self.send_header("Content-Type", "application/json")
            self.send_header("Content-Length", str(len(body)))
            self.end_headers()
            self.wfile.write(body)
            return
        self.send_error(404)


def run_mock() -> int:
    httpd = HTTPServer(("127.0.0.1", 0), MockIdP)
    port = httpd.server_address[1]
    issuer = f"http://127.0.0.1:{port}"
    c = NavcomClient("sample-public", "http://127.0.0.1:8765/callback", issuer=issuer)
    url, state, verifier = c.authorization_url()
    assert "code_challenge_method=S256" in url
    assert "client_credentials" not in url
    import threading

    t = threading.Thread(target=httpd.handle_request)
    t.start()
    tokens = c.exchange_code("mock-code", verifier)
    t.join(timeout=5)
    t = threading.Thread(target=httpd.handle_request)
    t.start()
    me = c.me(tokens["access_token"])
    t.join(timeout=5)
    httpd.server_close()
    print("sub=", me.get("sub"))
    print("rsi_handle=", me.get("rsi_handle"))
    print("avatar=", c.rsi_avatar(me["rsi_handle"]))
    return 0


def main() -> int:
    p = argparse.ArgumentParser()
    p.add_argument("--mock", action="store_true")
    p.add_argument("--issuer", default=os.environ.get("NAVCOM_ISSUER", "https://id-dev.navcom.ai"))
    p.add_argument("--client-id", default=os.environ.get("NAVCOM_CLIENT_ID", ""))
    p.add_argument("--code", default=os.environ.get("NAVCOM_CODE", ""))
    p.add_argument("--verifier", default=os.environ.get("NAVCOM_VERIFIER", ""))
    args = p.parse_args()
    if args.mock:
        return run_mock()
    if not (args.client_id and args.code and args.verifier):
        print("Need --mock or --client-id --code --verifier", file=sys.stderr)
        return 2
    c = NavcomClient(args.client_id, "http://127.0.0.1:8765/callback", issuer=args.issuer)
    tokens = c.exchange_code(args.code, args.verifier)
    me = c.me(tokens["access_token"])
    print("sub=", me.get("sub"))
    print("rsi_handle=", me.get("rsi_handle"))
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
