import os
from fastapi import FastAPI, File, UploadFile, Body
from ultralytics import YOLO
from dotenv import load_dotenv
import io
import shutil
from PIL import Image

from src.infrastructure.vision_service import VertexVisionService
from src.infrastructure.repository import MongoPalmOilRepository
from src.application.analyze_bunch import AnalyzeBunchUseCase

# Load environment variables
load_dotenv()

app = FastAPI(title="Palm Oil Ripeness Service (DDD)")

# Initialize YOLO model
yolo_model = YOLO('best.pt')

# Global state for the confidence threshold
current_conf = 0.25

# Initialize DDD Components
vision_service = VertexVisionService(
    project_id=os.getenv("PROJECT_ID", "your-project-id"),
    location=os.getenv("LOCATION", "us-central1")
)
repo = MongoPalmOilRepository(
    uri=os.getenv("MONGO_URI"),
    db_name=os.getenv("DB_NAME", "palm_oil_db"),
    collection_name=os.getenv("COLLECTION_NAME", "ffb_records")
)
analyze_use_case = AnalyzeBunchUseCase(vision_service, repo)

@app.get("/get_confidence")
async def get_confidence():
    """Returns the current confidence threshold used by the model."""
    return {
        "status": "success",
        "current_confidence": current_conf,
        "model_version": "best.pt"
    }

@app.post("/set_confidence")
async def set_confidence(threshold: float = Body(..., embed=True)):
    """Updates the confidence threshold globally."""
    global current_conf
    if 0.0 <= threshold <= 1.0:
        current_conf = threshold
        return {"status": "success", "new_confidence": current_conf}
    else:
        return {"status": "error", "message": "Threshold must be between 0.0 and 1.0"}

@app.post("/detect")
async def detect_ripeness(file: UploadFile = File(...)):
    # 1. Save file temporarily for YOLO and Vertex
    temp_path = f"temp_{file.filename}"
    with open(temp_path, "wb") as buffer:
        shutil.copyfileobj(file.file, buffer)

    try:
        # 2. Run YOLO detection
        img = Image.open(temp_path)
        results = yolo_model(img, conf=current_conf)
        
        detections = []
        for r in results:
            for box in r.boxes:
                detections.append({
                    "class": yolo_model.names[int(box.cls)],
                    "confidence": round(float(box.conf), 2),
                    "box": box.xyxy.tolist()[0]
                })

        # 3. If detections found, analyze the first one (or all) for deeper insights
        results_summary = []
        if detections:
            # For this MVP, we analyze the primary detection
            primary_detection = detections[0]
            record_id = analyze_use_case.execute(temp_path, primary_detection)
            
            return {
                "status": "success",
                "record_id": record_id,
                "detections": detections,
                "message": "FFB processed and archived successfully"
            }
        
        return {"status": "no_detection", "message": "No palm oil FFB detected"}

    finally:
        # Clean up temp file
        if os.path.exists(temp_path):
            os.remove(temp_path)

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)
