from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from typing import List, Optional
from pydantic import BaseModel, Field
import json

from db.db_connection import get_db
from db.models.lorry_model import Lorry  # <-- SQLAlchemy model only

router = APIRouter(
    prefix="/lorries",
    tags=["Lorries"]
)

# ===============================
# Pydantic Schemas
# ===============================
class LorryModel(BaseModel):
    lorry_size: str = Field(..., example="3-Ton Lorry")
    base_price: float = Field(..., example=150.00)
    price_per_km: float = Field(..., example=2.50)
    weight_kg: Optional[float] = Field(None, example=3000.00)
    length_m: float = Field(..., example=4.20)
    width_m: float = Field(..., example=2.00)
    height_m: float = Field(..., example=2.20)
    images: Optional[List[str]] = Field(
        None, example=["uploads/lorry_front.jpg", "uploads/lorry_back.jpg"]
    )
    additional_manpower_price: float = Field(
        0.0, example=80.00, description="Price per additional manpower"
    )
    man_power: Optional[int] = Field(None, example=3, description="Number of manpower available")

    class Config:
        json_schema_extra = {
            "example": {
                "lorry_size": "3-Ton Lorry",
                "base_price": 150.00,
                "price_per_km": 2.50,
                "weight_kg": 3000.00,
                "length_m": 4.20,
                "width_m": 2.00,
                "height_m": 2.20,
                "images": ["uploads/lorry_front.jpg", "uploads/lorry_back.jpg"],
                "additional_manpower_price": 80.00
            }
        }


class LorryResponse(LorryModel):
    id: int = Field(..., example=1)
    capacity: Optional[str] = Field(None, example="4.2m × 2.0m × 2.2m - 3000kg capacity")
    
class CostCalculationRequest(BaseModel):
    lorry_id: int = Field(..., example=1)
    distance: float = Field(..., example=25.5, description="Distance in kilometers")
    additional_services: Optional[dict] = Field(None, example={"manpower": True})

class CostCalculationResponse(BaseModel):
    lorry_id: int
    lorry_size: str
    base_cost: float
    distance_cost: float
    additional_cost: float
    total_cost: float
    distance_km: float
    price_per_km: float
    breakdown: dict


# ===============================
# Routes
# ===============================
@router.post("/", response_model=LorryResponse)
def add_lorry(lorry_data: LorryModel, db: Session = Depends(get_db)):
    try:
        new_lorry = Lorry(**lorry_data.model_dump())
        db.add(new_lorry)
        db.commit()
        db.refresh(new_lorry)
        return new_lorry
    except Exception as e:
        db.rollback()
        raise HTTPException(status_code=500, detail=f"Error creating lorry: {str(e)}")


@router.get("/", response_model=List[LorryResponse])
def list_lorries(db: Session = Depends(get_db)):
    """Get all lorries with enhanced information for frontend"""
    try:
        lorries = db.query(Lorry).order_by(Lorry.id.desc()).all()
        
        # Transform data to match frontend expectations
        enhanced_lorries = []
        for lorry in lorries:
            # Create capacity description
            capacity = f"{lorry.length_m}m × {lorry.width_m}m × {lorry.height_m}m"
            if lorry.weight_kg:
                capacity += f" - {lorry.weight_kg}kg capacity"
            
            enhanced_lorry = {
                "id": lorry.id,
                "lorry_size": lorry.lorry_size,
                "base_price": float(lorry.base_price),
                "price_per_km": float(lorry.price_per_km),
                "weight_kg": float(lorry.weight_kg) if lorry.weight_kg else None,
                "length_m": float(lorry.length_m),
                "width_m": float(lorry.width_m),
                "height_m": float(lorry.height_m),
                "images": lorry.images if lorry.images else [],
                "additional_manpower_price": float(lorry.additional_manpower_price),
                "man_power": lorry.man_power,
                "capacity": capacity
            }
            enhanced_lorries.append(enhanced_lorry)
        
        return enhanced_lorries
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Error fetching lorries: {str(e)}")


@router.get("/{lorry_id}", response_model=LorryResponse)
def get_lorry(lorry_id: int, db: Session = Depends(get_db)):
    """Get a specific lorry with enhanced information"""
    try:
        lorry = db.query(Lorry).filter_by(id=lorry_id).first()
        if not lorry:
            raise HTTPException(status_code=404, detail="Lorry not found")
        
        # Create capacity description
        capacity = f"{lorry.length_m}m × {lorry.width_m}m × {lorry.height_m}m"
        if lorry.weight_kg:
            capacity += f" - {lorry.weight_kg}kg capacity"
        
        enhanced_lorry = {
            "id": lorry.id,
            "lorry_size": lorry.lorry_size,
            "base_price": float(lorry.base_price),
            "price_per_km": float(lorry.price_per_km),
            "weight_kg": float(lorry.weight_kg) if lorry.weight_kg else None,
            "length_m": float(lorry.length_m),
            "width_m": float(lorry.width_m),
            "height_m": float(lorry.height_m),
            "images": lorry.images if lorry.images else [],
            "additional_manpower_price": float(lorry.additional_manpower_price),
            "man_power": lorry.man_power,
            "capacity": capacity
        }
        
        return enhanced_lorry
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Error fetching lorry: {str(e)}")


@router.put("/{lorry_id}/edit", response_model=LorryResponse)
def update_lorry(lorry_id: int, lorry_data: LorryModel, db: Session = Depends(get_db)):
    try:
        lorry = db.query(Lorry).filter_by(id=lorry_id).first()
        if not lorry:
            raise HTTPException(status_code=404, detail="Lorry not found")
        for key, value in lorry_data.model_dump().items():
            setattr(lorry, key, value)
        db.commit()
        db.refresh(lorry)
        return lorry
    except Exception as e:
        db.rollback()
        raise HTTPException(status_code=500, detail=f"Error updating lorry: {str(e)}")


@router.delete("/{lorry_id}/delete")
def delete_lorry(lorry_id: int, db: Session = Depends(get_db)):
    try:
        lorry = db.query(Lorry).filter_by(id=lorry_id).first()
        if not lorry:
            raise HTTPException(status_code=404, detail="Lorry not found")
        db.delete(lorry)
        db.commit()
        return {"result": "ok"}
    except Exception as e:
        db.rollback()
        raise HTTPException(status_code=500, detail=f"Error deleting lorry: {str(e)}")


@router.post("/bulk", response_model=List[LorryResponse], status_code=201)
def create_multiple_lorries(lorries: List[LorryModel], db: Session = Depends(get_db)):
    """
    Create multiple lorry records at once.
    """
    try:
        new_lorries_db = [Lorry(**lorry.model_dump()) for lorry in lorries]
        db.add_all(new_lorries_db)
        db.commit()
        for lorry in new_lorries_db:
            db.refresh(lorry)
        return new_lorries_db
    except Exception as e:
        db.rollback()
        raise HTTPException(status_code=500, detail=f"Error creating lorries: {str(e)}")


@router.post("/calculate-cost", response_model=CostCalculationResponse)
def calculate_lorry_cost(
    request: CostCalculationRequest,
    db: Session = Depends(get_db)
):
    """Calculate total cost for a lorry service"""
    try:
        lorry = db.query(Lorry).filter_by(id=request.lorry_id).first()
        if not lorry:
            raise HTTPException(status_code=404, detail="Lorry not found")
        
        # Calculate base cost
        base_cost = float(lorry.base_price)
        distance_cost = float(lorry.price_per_km) * request.distance
        
        # Calculate additional services cost
        additional_cost = 0
        breakdown = {
            "base_price": base_cost,
            "distance_calculation": {
                "distance_km": request.distance,
                "price_per_km": float(lorry.price_per_km),
                "distance_cost": distance_cost
            },
            "additional_services": {}
        }
        
        if request.additional_services:
            if request.additional_services.get("manpower"):
                manpower_cost = float(lorry.additional_manpower_price)
                additional_cost += manpower_cost
                breakdown["additional_services"]["manpower"] = manpower_cost
            
            if request.additional_services.get("packing"):
                packing_cost = 50.0  # Default packing cost
                additional_cost += packing_cost
                breakdown["additional_services"]["packing"] = packing_cost
        
        total_cost = base_cost + distance_cost + additional_cost
        breakdown["total_additional_cost"] = additional_cost
        breakdown["final_total"] = total_cost
        
        return {
            "lorry_id": lorry.id,
            "lorry_size": lorry.lorry_size,
            "base_cost": base_cost,
            "distance_cost": distance_cost,
            "additional_cost": additional_cost,
            "total_cost": total_cost,
            "distance_km": request.distance,
            "price_per_km": float(lorry.price_per_km),
            "breakdown": breakdown
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Error calculating cost: {str(e)}")


@router.get("/cost-estimate/{lorry_id}")
def get_cost_estimate(
    lorry_id: int,
    distance: float,
    manpower: bool = False,
    packing: bool = False,
    db: Session = Depends(get_db)
):
    """Quick cost estimate for a lorry (simplified endpoint for frontend)"""
    try:
        lorry = db.query(Lorry).filter_by(id=lorry_id).first()
        if not lorry:
            raise HTTPException(status_code=404, detail="Lorry not found")
        
        base_cost = float(lorry.base_price)
        distance_cost = float(lorry.price_per_km) * distance
        additional_cost = 0
        
        if manpower:
            additional_cost += float(lorry.additional_manpower_price)
        if packing:
            additional_cost += 50.0  # Default packing cost
        
        total_cost = base_cost + distance_cost + additional_cost
        
        return {
            "lorry_id": lorry.id,
            "lorry_size": lorry.lorry_size,
            "base_cost": base_cost,
            "distance_cost": distance_cost,
            "additional_cost": additional_cost,
            "total_cost": total_cost,
            "estimated_cost": f"{total_cost:.2f}",
            "capacity": f"{lorry.length_m}m × {lorry.width_m}m × {lorry.height_m}m" + (f" - {lorry.weight_kg}kg capacity" if lorry.weight_kg else ""),
            "manpower": lorry.man_power,
            "total_staff": (lorry.man_power + 1) if lorry.man_power else 2,
            "images": lorry.images if lorry.images else []
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Error calculating estimate: {str(e)}")



