"""
Routes API pour la gestion des pièces béton
"""
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.orm import Session
from typing import List, Optional
from app.database import get_db
from app.models.projet import Piece, Projet
from app.schemas.piece import PieceCreate, PieceUpdate, PieceResponse
import math

router = APIRouter(prefix="/api/pieces", tags=["Pièces"])


@router.get("/projet/{projet_id}", response_model=List[PieceResponse])
def lire_pieces_projet(
    projet_id: int,
    niveau_id: Optional[int] = None,
    db: Session = Depends(get_db)
):
    """
    Récupère toutes les pièces d'un projet (avec filtre optionnel par niveau)
    """
    query = db.query(Piece).filter(Piece.projet_id == projet_id)
    
    if niveau_id:
        query = query.filter(Piece.niveau_id == niveau_id)
    
    pieces = query.order_by(Piece.date_creation).all()
    return pieces


@router.get("/{piece_id}", response_model=PieceResponse)
def lire_piece(piece_id: int, db: Session = Depends(get_db)):
    """
    Récupère une pièce spécifique par son ID
    """
    piece = db.query(Piece).filter(Piece.id == piece_id).first()
    if not piece:
        raise HTTPException(status_code=404, detail="Pièce non trouvée")
    return piece


@router.post("/", response_model=PieceResponse, status_code=201)
def creer_piece(piece: PieceCreate, db: Session = Depends(get_db)):
    """
    Crée une nouvelle pièce
    """
    # Créer la pièce
    db_piece = Piece(**piece.model_dump())
    
    # Calculer les volumes et poids
    db_piece.calculer_volumes()
    
    db.add(db_piece)
    db.commit()
    db.refresh(db_piece)
    
    # Recalculer les totaux du projet
    _recalculer_projet(db_piece.projet_id, db)
    
    return db_piece


@router.put("/{piece_id}", response_model=PieceResponse)
def modifier_piece(
    piece_id: int,
    piece_update: PieceUpdate,
    db: Session = Depends(get_db)
):
    """
    Modifie une pièce existante
    """
    db_piece = db.query(Piece).filter(Piece.id == piece_id).first()
    if not db_piece:
        raise HTTPException(status_code=404, detail="Pièce non trouvée")
    
    # Mettre à jour les champs
    update_data = piece_update.model_dump(exclude_unset=True)
    for field, value in update_data.items():
        setattr(db_piece, field, value)
    
    # Recalculer les volumes
    db_piece.calculer_volumes()
    
    db.commit()
    db.refresh(db_piece)
    
    # Recalculer les totaux du projet
    _recalculer_projet(db_piece.projet_id, db)
    
    return db_piece


@router.delete("/{piece_id}", status_code=204)
def supprimer_piece(piece_id: int, db: Session = Depends(get_db)):
    """
    Supprime une pièce
    """
    db_piece = db.query(Piece).filter(Piece.id == piece_id).first()
    if not db_piece:
        raise HTTPException(status_code=404, detail="Pièce non trouvée")
    
    projet_id = db_piece.projet_id
    db.delete(db_piece)
    db.commit()
    
    # Recalculer les totaux du projet
    _recalculer_projet(projet_id, db)
    
    return None


@router.post("/{piece_id}/dupliquer", response_model=PieceResponse, status_code=201)
def dupliquer_piece(piece_id: int, db: Session = Depends(get_db)):
    """
    Duplique une pièce existante
    """
    piece_originale = db.query(Piece).filter(Piece.id == piece_id).first()
    if not piece_originale:
        raise HTTPException(status_code=404, detail="Pièce non trouvée")
    
    # Créer une copie
    piece_data = {
        "projet_id": piece_originale.projet_id,
        "niveau_id": piece_originale.niveau_id,
        "reference": piece_originale.reference + "-COPIE",
        "type_piece": piece_originale.type_piece,
        "quantite": piece_originale.quantite,
        "type_coulage": piece_originale.type_coulage,
        "epaisseur": piece_originale.epaisseur,
        "largeur": piece_originale.largeur,
        "longueur": piece_originale.longueur,
        "ajustement_volume": piece_originale.ajustement_volume,
        "type_beton": piece_originale.type_beton,
        "type_armature": piece_originale.type_armature,
        "poids_cfa": piece_originale.poids_cfa,
        "config_treillis": piece_originale.config_treillis,
        "becquet_type": piece_originale.becquet_type,
        "becquet_longueur": piece_originale.becquet_longueur,
        "becquet_auto": piece_originale.becquet_auto,
        "config_start": piece_originale.config_start,
        "config_inserts": piece_originale.config_inserts,
        "config_menuiserie": piece_originale.config_menuiserie,
        "convoi_exceptionnel": piece_originale.convoi_exceptionnel,
        "prix_unitaire_ht": piece_originale.prix_unitaire_ht,
        "notes": piece_originale.notes
    }
    
    db_piece = Piece(**piece_data)
    db_piece.calculer_volumes()
    
    db.add(db_piece)
    db.commit()
    db.refresh(db_piece)
    
    # Recalculer les totaux du projet
    _recalculer_projet(db_piece.projet_id, db)
    
    return db_piece


def _recalculer_projet(projet_id: int, db: Session):
    """
    Fonction interne pour recalculer les totaux d'un projet
    """
    projet = db.query(Projet).filter(Projet.id == projet_id).first()
    if not projet:
        return
    
    pieces = db.query(Piece).filter(Piece.projet_id == projet_id).all()
    
    poids_total = sum(p.poids_total for p in pieces)
    convoi = any(p.convoi_exceptionnel for p in pieces)
    nb_transports = max(1, int(poids_total / 25)) if poids_total > 0 else 0
    
    projet.poids_total = poids_total
    projet.nb_transports = nb_transports
    projet.convoi_exceptionnel = convoi
    
    db.commit()
