#!/usr/bin/env python3
"""Local CORS proxy for No Kings protest monitor.
Forwards requests from the browser to Bluesky/Twitter APIs,
bypassing CORS and SSL certificate issues.
"""
import http.server
import json
import urllib.request
import urllib.error
import ssl
import sys
from urllib.parse import urlparse, parse_qs

PORT = 8929

# Allow self-signed / internal certs
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE

ALLOWED_HOSTS = [
    'bluesky.onlyarag.com',
    'twitter.onlyarag.com',
    'public.api.bsky.app',
]


class ProxyHandler(http.server.BaseHTTPRequestHandler):
    def do_OPTIONS(self):
        self.send_response(200)
        self._cors_headers()
        self.end_headers()

    def do_GET(self):
        self._proxy('GET')

    def do_POST(self):
        self._proxy('POST')

    def _cors_headers(self):
        self.send_header('Access-Control-Allow-Origin', '*')
        self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
        self.send_header('Access-Control-Allow-Headers', 'Content-Type')

    def _proxy(self, method):
        # Extract target URL from query param: /proxy?url=https://...
        parsed = urlparse(self.path)
        params = parse_qs(parsed.query)
        target_url = params.get('url', [None])[0]

        if not target_url:
            self.send_response(400)
            self._cors_headers()
            self.end_headers()
            self.wfile.write(b'{"error": "Missing url parameter"}')
            return

        # Security: only proxy to allowed hosts
        target_host = urlparse(target_url).hostname
        if target_host not in ALLOWED_HOSTS:
            self.send_response(403)
            self._cors_headers()
            self.end_headers()
            self.wfile.write(json.dumps({"error": f"Host {target_host} not allowed"}).encode())
            return

        # Read request body for POST
        body = None
        if method == 'POST':
            content_length = int(self.headers.get('Content-Length', 0))
            body = self.rfile.read(content_length) if content_length > 0 else None

        try:
            req = urllib.request.Request(target_url, data=body, method=method)
            req.add_header('Content-Type', 'application/json')
            req.add_header('Accept', 'application/json')

            with urllib.request.urlopen(req, context=ctx, timeout=15) as resp:
                data = resp.read()
                self.send_response(resp.status)
                self._cors_headers()
                self.send_header('Content-Type', resp.headers.get('Content-Type', 'application/json'))
                self.end_headers()
                self.wfile.write(data)

        except urllib.error.HTTPError as e:
            self.send_response(e.code)
            self._cors_headers()
            self.end_headers()
            self.wfile.write(e.read())

        except Exception as e:
            self.send_response(502)
            self._cors_headers()
            self.end_headers()
            self.wfile.write(json.dumps({"error": str(e)}).encode())

    def log_message(self, format, *args):
        target = ''
        if len(args) > 0:
            parsed = urlparse(str(args[0]).split(' ')[1] if ' ' in str(args[0]) else '')
            params = parse_qs(parsed.query)
            url = params.get('url', [''])[0]
            if url:
                target = f' -> {url[:80]}'
        sys.stderr.write(f"[proxy] {args[0]}{target}\n")


if __name__ == '__main__':
    server = http.server.HTTPServer(('127.0.0.1', PORT), ProxyHandler)
    print(f'CORS proxy running on http://localhost:{PORT}')
    print(f'Allowed hosts: {", ".join(ALLOWED_HOSTS)}')
    server.serve_forever()
