from fastapi import APIRouter, HTTPException, Query, Path from pydantic import BaseModel from typing import List, Optional from uuid import UUID from datetime import datetime from src.config import logger from src.models import Weights from src.services import ComparativeWeightService class ComparitiveWeight(BaseModel): id: UUID rfp_id: UUID technical_weight: Weights management_weight: Weights past_performance_weight: Weights price_weight: Weights strengths_weight: float weaknesses_weight: float flag: Optional[bool] = False created_at: datetime updated_at: datetime class ResponseComparativeWeight(BaseModel): status: str data: Optional[List[ComparitiveWeight]] class DeleteResponse(BaseModel): status: str class ComparativeWeightRequest(BaseModel): technical_weight: Optional[Weights] = None management_weight: Optional[Weights] = None past_performance_weight: Optional[Weights] = None price_weight: Optional[Weights] = None strengths_weight: Optional[float] = None weaknesses_weight: Optional[float] = None flag: Optional[bool] = None class ComparativeWeightController: def __init__(self): self.comparative_weight_service = ComparativeWeightService self.router = APIRouter() self.router.add_api_route( "/rfps/{rfp_id}/comparative-weights", self.get_comparative_weights_by_rfp_id, methods=["GET"], response_model=ResponseComparativeWeight, tags=["Comparative Weights by RFP ID"], ) self.router.add_api_route( "/rfps/{rfp_id}/comparative-weights/{id}", self.get_comparative_weights_by_id, methods=["GET"], response_model=ResponseComparativeWeight, tags=["Comparative Weights by RFP ID and ID"], ) self.router.add_api_route( "/rfps/{rfp_id}/comparative-weights", self.create_comparative_weights, methods=["POST"], response_model=ResponseComparativeWeight, tags=["Comparative Weights by RFP ID"], ) self.router.add_api_route( "/rfps/{rfp_id}/comparative-weights/{id}", self.update_comparative_weights_by_id, methods=["PUT"], response_model=ResponseComparativeWeight, tags=["Comparative Weights by RFP ID and ID"], ) self.router.add_api_route( "/rfps/{rfp_id}/comparative-weights", self.update_comparative_weights, methods=["PUT"], response_model=ResponseComparativeWeight, tags=["Comparative Weights by RFP ID"], ) self.router.add_api_route( "/rfps/{rfp_id}/comparative-weights", self.delete_comparative_weights, methods=["DELETE"], response_model=DeleteResponse, tags=["Comparative Weights by RFP ID"], ) self.router.add_api_route( "/rfps/{rfp_id}/comparative-weights/{id}", self.delete_comparative_weights_by_id, methods=["DELETE"], response_model=DeleteResponse, tags=["Comparative Weights by RFP ID and ID"], ) async def get_comparative_weights_by_rfp_id(self, rfp_id: str = Path(...)): try: async with self.comparative_weight_service() as service: comparative_weights = await service.get_comparative_weights( rfp_id=rfp_id ) return ResponseComparativeWeight( status="success", data=[ ComparitiveWeight(**comparative_weight) for comparative_weight in comparative_weights ], ) except Exception as e: logger.error(f"Error getting comparative weights by rfp id: {e}") raise HTTPException( status_code=500, detail="Error getting comparative weights by rfp id" ) async def get_comparative_weights_by_id( self, rfp_id: str = Path(...), id: str = Path(...) ): try: async with self.comparative_weight_service() as service: comparative_weights = await service.get_comparative_weights( rfp_id=rfp_id, id=id ) return ResponseComparativeWeight( status="success", data=[ ComparitiveWeight(**comparative_weight) for comparative_weight in comparative_weights ], ) except Exception as e: logger.error(f"Error getting comparative weights by id: {e}") raise HTTPException( status_code=500, detail="Error getting comparative weights by id" ) async def create_comparative_weights( self, comparative_weights: ComparativeWeightRequest, rfp_id: str = Path(...) ): try: async with self.comparative_weight_service() as service: comparative_weights = await service.create_comparative_weights( rfp_id=rfp_id, comparative_weights=comparative_weights.model_dump( mode="json", exclude_unset=True ), ) return ResponseComparativeWeight( status="success", data=[ ComparitiveWeight(**comparative_weight) for comparative_weight in comparative_weights ], ) except Exception as e: logger.error(f"Error creating comparative weights: {e}") raise HTTPException( status_code=500, detail="Error creating comparative weights" ) async def update_comparative_weights( self, comparative_weights: ComparativeWeightRequest, rfp_id: str = Path(...) ): try: async with self.comparative_weight_service() as service: comparative_weights = await service.update_comparative_weights( rfp_id=rfp_id, comparative_weights=comparative_weights.model_dump( mode="json", exclude_unset=True ), ) return ResponseComparativeWeight( status="success", data=[ ComparitiveWeight(**comparative_weight) for comparative_weight in comparative_weights ], ) except Exception as e: logger.error(f"Error updating comparative weights: {e}") raise HTTPException( status_code=500, detail="Error updating comparative weights" ) async def update_comparative_weights_by_id( self, comparative_weights: ComparativeWeightRequest, rfp_id: str = Path(...), id: str = Path(...), ): try: async with self.comparative_weight_service() as service: comparative_weights = await service.update_comparative_weights( rfp_id=rfp_id, id=id, comparative_weights=comparative_weights.model_dump( mode="json", exclude_unset=True ), ) return ResponseComparativeWeight( status="success", data=[ ComparitiveWeight(**comparative_weight) for comparative_weight in comparative_weights ], ) except Exception as e: logger.error(f"Error updating comparative weights by id: {e}") raise HTTPException( status_code=500, detail="Error updating comparative weights by id" ) async def delete_comparative_weights(self, rfp_id: str = Path(...)): try: async with self.comparative_weight_service() as service: await service.delete_comparative_weights(rfp_id=rfp_id) return DeleteResponse(status="success") except Exception as e: logger.error(f"Error deleting comparative weights: {e}") raise HTTPException( status_code=500, detail="Error deleting comparative weights" ) async def delete_comparative_weights_by_id( self, rfp_id: str = Path(...), id: str = Path(...) ): try: async with self.comparative_weight_service() as service: await service.delete_comparative_weights(rfp_id=rfp_id, id=id) return DeleteResponse(status="success") except Exception as e: logger.error(f"Error deleting comparative weights: {e}") raise HTTPException( status_code=500, detail="Error deleting comparative weights" )