"""sdkspindle trial proxy — Vercel Serverless Function.

Endpoint: POST /api/query
  Body: {"question": "...", "context": "...", "model": "gemini-3-flash-preview"}
  Returns: {"answer": "..."} or {"error": "..."}
"""

import json
import os
import time
import hashlib
from http.server import BaseHTTPRequestHandler

from google import genai

_rate_store = {}
RATE_LIMIT = 20
RATE_WINDOW = 86400
DEFAULT_MODEL = "gemini-3-flash-preview"

ALLOWED_MODELS = {
    "gemini-3-flash-preview",
    "gemini-3.1-pro-preview",
    "gemini-2.5-flash",
    "gemini-2.5-flash-lite",
}

SYSTEM_PROMPT = """You are sdkspindle, an expert on the com.google.genai Java SDK (google-genai).
You have access to the extracted SDK API reference below.

Rules:
- Answer with EXACT Java/Kotlin types, method signatures, and field names from the reference.
- When showing code, use Kotlin syntax (the primary consumer language).
- Always show the correct import statements.
- If a field returns Optional<T>, always show the .orElse() unwrapping.
- If a builder method has varargs overloads, mention both List<T> and varargs options.
- Be concise. Developers want the answer, not an essay.
- If the question is about something not in the reference, say so clearly."""

MAX_CONTEXT_SIZE = 50_000
MAX_QUESTION_LEN = 500


def _hash_ip(ip):
    return hashlib.sha256(ip.encode()).hexdigest()[:16]


def _check_rate_limit(ip):
    now = time.time()
    h = _hash_ip(ip)
    entry = _rate_store.get(h)
    if not entry or now - entry["t"] > RATE_WINDOW:
        _rate_store[h] = {"c": 1, "t": now}
        return True, RATE_LIMIT - 1, int(now + RATE_WINDOW)
    if entry["c"] >= RATE_LIMIT:
        return False, 0, int(entry["t"] + RATE_WINDOW)
    entry["c"] += 1
    return True, RATE_LIMIT - entry["c"], int(entry["t"] + RATE_WINDOW)


def _call_gemini(question, context, model):
    api_key = os.environ.get("GOOGLE_API_KEY")
    if not api_key:
        raise RuntimeError("Server misconfigured: no GOOGLE_API_KEY")

    client = genai.Client(api_key=api_key)
    response = client.models.generate_content(
        model=model,
        contents=f"SDK API Reference (relevant subset):\n```json\n{context}\n```\n\nQuestion: {question}",
        config={
            "system_instruction": SYSTEM_PROMPT,
            "temperature": 0.1,
            "max_output_tokens": 2048,
        },
    )
    return response.text or "(empty response)"


def _respond(handler, status, body, remaining=None, reset_at=None):
    handler.send_response(status)
    handler.send_header("Content-Type", "application/json")
    handler.send_header("Access-Control-Allow-Origin", "*")
    if remaining is not None:
        handler.send_header("X-RateLimit-Remaining", str(remaining))
    if reset_at is not None:
        handler.send_header("X-RateLimit-Reset", str(reset_at))
    handler.end_headers()
    handler.wfile.write(json.dumps(body).encode())


class handler(BaseHTTPRequestHandler):
    def do_POST(self):
        client_ip = self.headers.get("x-forwarded-for", self.client_address[0]).split(",")[0].strip()
        allowed, remaining, reset_at = _check_rate_limit(client_ip)

        if not allowed:
            return _respond(self, 429, {
                "error": f"Rate limit exceeded ({RATE_LIMIT}/day). Set your own GOOGLE_API_KEY for unlimited.",
            }, remaining, reset_at)

        content_length = int(self.headers.get("Content-Length", 0))
        if content_length > 100_000:
            return _respond(self, 413, {"error": "Request too large"})

        try:
            data = json.loads(self.rfile.read(content_length))
        except json.JSONDecodeError:
            return _respond(self, 400, {"error": "Invalid JSON"})

        question = (data.get("question") or "")[:MAX_QUESTION_LEN]
        context = (data.get("context") or "")[:MAX_CONTEXT_SIZE]
        model = data.get("model", DEFAULT_MODEL)

        if not question:
            return _respond(self, 400, {"error": "Missing 'question' field"})
        if model not in ALLOWED_MODELS:
            model = DEFAULT_MODEL

        try:
            answer = _call_gemini(question, context, model)
        except Exception as e:
            return _respond(self, 502, {"error": f"Gemini error: {str(e)[:200]}"})

        _respond(self, 200, {"answer": answer, "remaining": remaining, "model": model}, remaining, reset_at)

    def do_OPTIONS(self):
        self.send_response(200)
        self.send_header("Access-Control-Allow-Origin", "*")
        self.send_header("Access-Control-Allow-Methods", "POST, OPTIONS")
        self.send_header("Access-Control-Allow-Headers", "Content-Type")
        self.end_headers()
