# gateway.py — FastAPI + Moodle + Gemini + RAG

from __future__ import annotations

import os
import json
import logging
from pathlib import Path

import requests
from dotenv import load_dotenv

from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel

from rag import Retriever, build_prompt


BASE_DIR = Path(__file__).resolve().parent
load_dotenv(BASE_DIR / ".env")

MODEL_API_URL = os.getenv("MODEL_API_URL", "").strip()
MODEL_API_KEY = os.getenv("MODEL_API_KEY", "").strip()
MODEL_NAME = os.getenv("MODEL_MODEL", os.getenv("MODEL_NAME", "gemini-2.5-flash")).strip()
REQUEST_TIMEOUT = int(os.getenv("REQUEST_TIMEOUT", "30"))

ALLOWED_ORIGINS = [
    x.strip()
    for x in os.getenv("ALLOWED_ORIGINS", "*").split(",")
    if x.strip()
]

logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
logger = logging.getLogger("assistant")

app = FastAPI(title="Assistant Gateway", version="1.0.0")

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

session = requests.Session()


class ChatRequest(BaseModel):
    courseid: int
    question: str
    course_name: str = "Curso Moodle"


@app.get("/")
def home():
    return {
        "status": "ok",
        "service": "assistant",
        "model": MODEL_NAME,
    }


@app.get("/health")
def health():
    return {"ok": True}


@app.get("/courses/{courseid}/rag-status")
def rag_status(courseid: int):
    try:
        retriever = Retriever(courseid)
        chunks = len(retriever.chunks)

        return {
            "ok": True,
            "courseid": courseid,
            "chunks": chunks,
            "rag_available": chunks > 0,
        }

    except Exception:
        return {
            "ok": False,
            "courseid": courseid,
            "chunks": 0,
            "rag_available": False,
        }


def call_llm_openai(prompt: str) -> str:
    if not MODEL_API_URL:
        return "MODEL_API_URL não configurado."

    if not MODEL_API_KEY:
        return "MODEL_API_KEY não configurado."

    if not MODEL_NAME:
        return "MODEL_MODEL não configurado."

    headers = {
        "Authorization": f"Bearer {MODEL_API_KEY}",
        "Content-Type": "application/json",
    }

    payload = {
        "model": MODEL_NAME,
        "messages": [
            {
                "role": "system",
                "content": (
                    "Você é um assistente educacional integrado ao Moodle. "
                    "Responda apenas usando os conteúdos fornecidos no contexto. "
                    "Não invente informação. "
                    "Use português claro, didático e objetivo."
                ),
            },
            {
                "role": "user",
                "content": prompt,
            },
        ],
        "temperature": 0.2,
    }

    try:
        response = session.post(
            MODEL_API_URL,
            headers=headers,
            json=payload,
            timeout=REQUEST_TIMEOUT,
        )

        if response.status_code >= 400:
            logger.error(response.text)
            raise HTTPException(
                status_code=502,
                detail=f"Erro Gemini: {response.status_code} - {response.text}",
            )

        data = response.json()

        answer = (
            data.get("choices", [{}])[0]
            .get("message", {})
            .get("content", "")
            .strip()
        )

        return answer or "O Gemini respondeu vazio."

    except HTTPException:
        raise

    except Exception as e:
        logger.error(str(e))
        raise HTTPException(
            status_code=502,
            detail=f"Falha ao contactar Gemini: {e}",
        )


@app.post("/chat")
def chat(req: ChatRequest):
    question = req.question.strip()

    if not question:
        raise HTTPException(status_code=400, detail="Pergunta vazia.")

    try:
        retriever = Retriever(req.courseid)
        passages = retriever.search(question, k=6)

        if not passages:
            return {
                "answer": "Não encontrei conteúdos relevantes nos materiais deste curso."
            }

        prompt = build_prompt(
            course_name=req.course_name,
            question=question,
            passages=passages,
        )

        answer = call_llm_openai(prompt)

        return {
            "answer": answer
        }

    except FileNotFoundError:
        raise HTTPException(
            status_code=404,
            detail=f"O índice do curso {req.courseid} não existe. Execute ingest.py primeiro.",
        )

    except Exception as e:
        logger.error(str(e))
        raise HTTPException(status_code=500, detail=str(e))


@app.post("/ask")
def ask(req: ChatRequest):
    return chat(req)


if __name__ == "__main__":
    import uvicorn

    uvicorn.run(
        "gateway:app",
        host="0.0.0.0",
        port=8000,
        reload=True,
    )
