from sqlalchemy import func
from backend.app.db.models.recommendations import (
    PlanModel,
    PlanRecommendations,
    Recommendation,
    ScenarioModel,
)


def aggregate_portfolio_recommendations(
    session,
    portfolio_id: int,
    scenario_id: int,
    total_valuation_increase: float,
    labour_days: float,
    aggregated_data: dict,
):
    # Aggregate multiple fields
    aggregates = (
        session.query(
            func.sum(Recommendation.estimated_cost).label("cost"),
            func.sum(Recommendation.total_work_hours).label("total_work_hours"),
            func.sum(Recommendation.kwh_savings).label("energy_savings"),
            func.sum(Recommendation.co2_equivalent_savings).label(
                "co2_equivalent_savings"
            ),
            func.sum(Recommendation.energy_cost_savings).label("energy_cost_savings"),
        )
        .join(
            PlanRecommendations,
            PlanRecommendations.recommendation_id == Recommendation.id,
        )
        .join(PlanModel, PlanModel.id == PlanRecommendations.plan_id)
        .filter(
            PlanModel.portfolio_id == portfolio_id,
            PlanModel.scenario_id == scenario_id,
            Recommendation.default == True,
        )
        .one()
    )

    # Contingeny and funding are in the aggregated data
    aggregates_dict = {
        "cost": aggregates.cost or 0,
        "total_work_hours": aggregates.total_work_hours or 0,
        "energy_savings": aggregates.energy_savings or 0,
        "co2_equivalent_savings": aggregates.co2_equivalent_savings or 0,
        "energy_cost_savings": aggregates.energy_cost_savings or 0,
        **aggregated_data,
    }

    # Get the scenario and update the fields. This data needs to be stored against the scenario, not the portfolio
    portfolio_scenario = session.query(ScenarioModel).filter_by(id=scenario_id).one()

    # Update the data
    for key, value in aggregates_dict.items():
        setattr(portfolio_scenario, key, value)

    # Insert total valuation increase and labour days
    portfolio_scenario.property_valuation_increase = total_valuation_increase
    portfolio_scenario.labour_days = labour_days

    # Merge the updated portfolio plan back into the session
    session.merge(portfolio_scenario)
    session.flush()
