from __future__ import annotations from enum import Enum from typing import Literal from pydantic import BaseModel, Field class InstallmentType(str, Enum): equal = "equal" decreasing = "decreasing" class OverpaymentEffect(str, Enum): shorten = "shorten" lower_payment = "lower_payment" class RateChange(BaseModel): month: int = Field(ge=1, description="Miesiac od startu kredytu") annual_rate: float = Field(ge=0, le=30, description="Roczne oprocentowanie procentowo") class Overpayment(BaseModel): month: int = Field(ge=1) amount: float = Field(gt=0) repeat: Literal["once", "monthly", "yearly"] = "once" until_month: int | None = Field(default=None, ge=1) class SimulationRequest(BaseModel): principal: float = Field(gt=0) years: int = Field(ge=1, le=50) margin: float = Field(ge=0, le=20, default=2.0) base_rate: float = Field(ge=0, le=30, default=5.75) installment_type: InstallmentType = InstallmentType.equal overpayment_effect: OverpaymentEffect = OverpaymentEffect.shorten rate_changes: list[RateChange] = Field(default_factory=list) overpayments: list[Overpayment] = Field(default_factory=list) class ScheduleRow(BaseModel): month: int rate: float payment: float principal_part: float interest_part: float overpayment: float remaining: float class Summary(BaseModel): months: int total_paid: float total_interest: float total_overpayment: float interest_saved: float months_saved: int baseline_interest: float baseline_months: int average_payment: float max_payment: float class SimulationResponse(BaseModel): schedule: list[ScheduleRow] summary: Summary