from __future__ import annotations

from dataclasses import dataclass
from decimal import Decimal
from typing import Any

from app.schemas.budget import BudgetBalanceRead


DEFAULT_SUBJECT_AMOUNTS: dict[str, Decimal] = {
    "travel": Decimal("600000.00"),
    "meal": Decimal("420000.00"),
    "office": Decimal("180000.00"),
    "communication": Decimal("120000.00"),
}

BUDGET_SUBJECT_LABELS = {
    "travel": "差旅",
    "communication": "通信",
    "meal": "招待费",
    "office": "办公用品",
}
SUPPORTED_BUDGET_SUBJECT_CODES = frozenset(DEFAULT_SUBJECT_AMOUNTS)
SUBJECT_CODE_ALIASES = {
    "entertainment": "meal",
    "purchase": "office",
}

MUTATING_TRANSACTION_TYPES = {"adjust", "reserve", "release", "consume", "rollback"}


class BudgetControlError(ValueError):
    def __init__(self, reasons: list[str], *, flags: list[dict[str, Any]] | None = None) -> None:
        self.reasons = [reason for reason in reasons if reason]
        self.flags = list(flags or [])
        super().__init__("；".join(self.reasons) or "预算校验未通过")


@dataclass(frozen=True)
class BudgetBalance:
    total_amount: Decimal
    reserved_amount: Decimal
    consumed_amount: Decimal
    available_amount: Decimal
    usage_rate: Decimal

    def to_read(self) -> BudgetBalanceRead:
        return BudgetBalanceRead(
            total_amount=self.total_amount,
            reserved_amount=self.reserved_amount,
            consumed_amount=self.consumed_amount,
            available_amount=self.available_amount,
            usage_rate=self.usage_rate,
        )
