from decimal import Decimal

from flask import jsonify, request, abort

from app.blueprints.api import api_bp
from app.extensions import db
from app.models.account import Account
from app.models.settings import Settings
from app.services.amortization import (
    calculate_avalanche, calculate_snowball,
    calculate_highest_balance, calculate_proportional, calculate_custom,
)

_STRATEGY_CALC = {
    "avalanche":       calculate_avalanche,
    "snowball":        calculate_snowball,
    "highest_balance": calculate_highest_balance,
    "proportional":    calculate_proportional,
}


def _credit_card_dicts():
    cards = Account.query.filter_by(type="credit", is_active=True).all()
    return [
        {
            "id": c.id,
            "name": c.name,
            "balance": c.current_balance or Decimal("0"),
            "apr": c.apr or Decimal("0"),
            "min_payment": c.min_payment or Decimal("0"),
        }
        for c in cards
        if (c.current_balance or Decimal("0")) > Decimal("0")
    ]


@api_bp.route('/paydown/schedule/<strategy_name>')
def paydown_schedule(strategy_name):
    if strategy_name not in _STRATEGY_CALC and strategy_name != "custom":
        abort(404)

    card_dicts = _credit_card_dicts()
    settings = Settings.query.first()
    extra = settings.extra_monthly_payment if settings else Decimal("0")

    if strategy_name == "custom":
        result = calculate_custom(card_dicts, {})
    else:
        result = _STRATEGY_CALC[strategy_name](card_dicts, extra)

    return jsonify(result.per_card_schedule)


@api_bp.route('/paydown/calculate-custom', methods=['POST'])
def calculate_custom_strategy():
    """Recalculate the custom strategy with user-specified per-card amounts."""
    data = request.get_json(silent=True) or {}
    card_dicts = _credit_card_dicts()

    allocations = {}
    for card in card_dicts:
        key = str(card["id"])
        raw = str(data.get(key, "0"))
        try:
            allocations[card["id"]] = Decimal(raw)
        except Exception:
            allocations[card["id"]] = Decimal("0")

    result = calculate_custom(card_dicts, allocations)

    return jsonify({
        "strategy": result.strategy,
        "months_to_payoff": result.months_to_payoff,
        "total_interest_paid": str(result.total_interest_paid),
        "payoff_date": result.payoff_date.isoformat(),
        "per_card_schedule": result.per_card_schedule,
    })
