from fastapi import FastAPI, HTTPException, Request, Response
from fastapi.middleware.cors import CORSMiddleware
from contextlib import asynccontextmanager
from connection import prisma
from schemas import ComparisonResponse, RecommendationRequest
import ml_core
import services

@asynccontextmanager
async def lifespan(app: FastAPI):
    print("⏳ Menghubungkan ke Database Neon...")
    await prisma.connect()
    
    print("🤖 Memuat Asset Machine Learning (XGBoost)...")
    ml_core.load_ml_assets()
    
    yield  
    
    print("🔌 Memutuskan koneksi database...")
    await prisma.disconnect()

app = FastAPI(
    title="Tokopedia Laptop Recommendation API",
    description="Backend analisis sentimen ulasan laptop menggunakan XGBoost - Syafrizal Wd Mahendra",
    lifespan=lifespan
)

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

@app.post("/recommend", response_model=ComparisonResponse)
async def recommend_laptop(request: Request, data: RecommendationRequest): 
    if not ml_core.model_optimized:
        raise HTTPException(
            status_code=500, 
            detail="Model Machine Learning belum siap atau gagal dimuat."
        )

    results = []
    
    for index, candidate in enumerate(data.candidates):
        if await request.is_disconnected():
            print("🛑 Sinyal Cancel diterima! Menghentikan proses AI.")
            return Response(status_code=204)

        print(f"🔄 Memproses ulasan untuk: {candidate.name}...")
        
        try:
            result = await services.process_product_reviews(
                candidate=candidate, 
                user_email=data.user_email,
                metric_id=data.metric_id,
                brand_id=data.brand_id,
                request=request
            )
            
            if result:
                results.append(result)
                
        except Exception as e:
            print(f"⚠️ Gagal memproses {candidate.name}: {str(e)}")
            continue 

    if not results:
        raise HTTPException(
            status_code=400, 
            detail="Tidak ada ulasan valid yang berhasil dianalisis dari produk yang diberikan."
        )

    try:
        sorted_results = sorted(
            results, 
            key=lambda x: x.general_score if hasattr(x, 'general_score') else x["general_score"], 
            reverse=True
        )
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Gagal mengurutkan hasil analisis: {str(e)}")

    winner = sorted_results[0]

    return {
        "user_email": data.user_email,
        "brand_id": data.brand_id,
        "winning_product": winner.name if hasattr(winner, 'name') else winner["name"], 
        "details": sorted_results, 
        "metric_id": data.metric_id
    }