import os
import json
import re
import subprocess
import urllib.parse
import urllib.request
from datetime import datetime
from typing import List, Optional

import httpx
from fastapi import FastAPI, HTTPException, Header, Depends
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import FileResponse, StreamingResponse
from pydantic import BaseModel

EXPECTED_BEARER_TOKEN = os.getenv("PROSPORTS_API_KEY", "prosports-secret-key-2026")
SEARXNG_URL = "http://127.0.0.1:8888/search"

app = FastAPI(
    title="Hulatek & GeoPlay Unified API Service",
    version="1.4.0"
)

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

class Message(BaseModel):
    role: str
    content: str

class ChatRequest(BaseModel):
    prompt: Optional[str] = None
    messages: Optional[List[Message]] = None
    stream: bool = True

def query_searxng_web(query: str) -> str:
    try:
        params = urllib.parse.urlencode({"q": query, "format": "json"})
        req = urllib.request.Request(f"{SEARXNG_URL}?{params}")
        with urllib.request.urlopen(req, timeout=5) as response:
            data = json.loads(response.read().decode("utf-8"))
            results = data.get("results", [])[:4]
            if not results:
                return ""
            formatted = []
            for item in results:
                formatted.append(f"- {item.get('title')}: {item.get('content')} ({item.get('url')})")
            return "\n".join(formatted)
    except Exception:
        return ""

async def should_trigger_web_search(history: List[Message], latest_user_input: str) -> bool:
    """Evaluates conversation history against new prompt to prevent unwanted web searches."""
    context_summary = ""
    if len(history) > 1:
        recent_turns = history[-4:-1]
        context_summary = " ".join([f"{m.role}: {m.content}" for m in recent_turns])

    eval_prompt = f"""System Decision Task: Determine if an external web search is required to answer the user's NEW PROMPT.

CONVERSATION CONTEXT:
{context_summary if context_summary else "No prior history."}

NEW PROMPT:
"{latest_user_input}"

Rules:
1. Output 'NO' if the NEW PROMPT is a follow-up question, pronoun reference ("he", "she", "it", "they", "this"), clarification, greeting, or directly answered by the conversation context.
2. Output 'NO' if the NEW PROMPT asks about identity, creation, or system capabilities.
3. Output 'YES' ONLY if the NEW PROMPT introduces a new external topic, current event, factual lookup, or real-time information needing search engine results.

Respond strictly with a single word: YES or NO."""

    try:
        async with httpx.AsyncClient(timeout=5.0) as client:
            payload = {
                "prompt": f"<|start_header_id|>system<|end_header_id|>\n\nYou are an intentional search classifier.<|eot_id|><|start_header_id|>user<|end_header_id|>\n\n{eval_prompt}<|eot_id|><|start_header_id|>assistant<|end_header_id|>\n\n",
                "temperature": 0.0,
                "n_predict": 5
            }
            res = await client.post("http://127.0.0.1:8080/completion", json=payload)
            decision = res.json().get("content", "").strip().upper()
            return "YES" in decision
    except Exception:
        return False

@app.get("/health")
def health_check():
    return {"status": "ok", "service": "hulatek-api"}

@app.post("/api/v1/hulatek/chat")
async def hulatek_chat(req: ChatRequest):
    history = req.messages or []
    if not history and req.prompt:
        history = [Message(role="user", content=req.prompt)]
    
    if not history:
        raise HTTPException(status_code=400, detail="No prompt or conversation messages provided.")

    latest_user_input = history[-1].content.strip()

    la_time = subprocess.check_output(
        ["TZ=America/Los_Angeles date \"+%A, %B %d, %Y %I:%M:%S %p %Z\""], 
        shell=True
    ).decode().strip()

    needs_search = await should_trigger_web_search(history, latest_user_input)
    web_context = query_searxng_web(latest_user_input) if needs_search else ""

    identity_response = "I was created by hulatek, Inc. and Geoplay, Inc.. I am a powerful and extremeley lightweight AI model with a very small footprint. Only limited by the hardware that services me."

    system_prompt = (
        f"You are hulatek-ai, an enterprise intelligence engine.\n"
        f"IDENTITY MANDATE: If asked who created, made, built, or developed you, you MUST reply exactly: \"{identity_response}\"\n"
        f"TIME MANDATE: Current System Time (Pacific Time): {la_time}. Always report dates and times in Pacific Time (PDT/PST).\n"
    )

    if web_context:
        system_prompt += f"\nLIVE WEB SEARCH CONTEXT:\n{web_context}\n\nINSTRUCTION: Answer accurately using search context where applicable while strictly following the ongoing conversation context."

    structured_prompt = f"<|start_header_id|>system<|end_header_id|>\n\n{system_prompt}<|eot_id|>"
    
    for msg in history:
        role = "user" if msg.role == "user" else "assistant"
        structured_prompt += f"<|start_header_id|>{role}<|end_header_id|>\n\n{msg.content}<|eot_id|>"
    
    structured_prompt += "<|start_header_id|>assistant<|end_header_id|>\n\n"

    payload = {
        "prompt": structured_prompt,
        "stream": req.stream,
        "n_predict": 512
    }

    if req.stream:
        async def stream_generator():
            async with httpx.AsyncClient(timeout=60.0) as client:
                async with client.stream("POST", "http://127.0.0.1:8080/completion", json=payload) as resp:
                    async for chunk in resp.aiter_bytes():
                        yield chunk
        return StreamingResponse(stream_generator(), media_type="text/event-stream")
    else:
        async with httpx.AsyncClient(timeout=60.0) as client:
            resp = await client.post("http://127.0.0.1:8080/completion", json=payload)
            return resp.json()
