from __future__ import annotations

from datetime import UTC, datetime
from decimal import Decimal, InvalidOperation
from sqlite3 import Connection
from uuid import uuid4

from fastapi import HTTPException

ACCOUNT_TYPES = {"checking", "credit_card", "cash", "savings", "investment_cash", "virtual", "reserve", "other"}


def now() -> str:
    return datetime.now(UTC).replace(microsecond=0).isoformat().replace("+00:00", "Z")


def new_id(prefix: str) -> str:
    return f"{prefix}_{uuid4().hex[:16]}"


def require_decimal_text(value: str, field: str = "amount") -> str:
    try:
        parsed = Decimal(str(value))
    except (InvalidOperation, ValueError) as exc:
        raise HTTPException(status_code=422, detail=f"Invalid decimal for {field}") from exc
    if parsed <= 0:
        raise HTTPException(status_code=422, detail=f"{field} must be positive")
    return format(parsed, "f")


def validate_currency(value: str) -> str:
    cur = str(value or "").strip().upper()
    if len(cur) != 3 or not cur.isalpha():
        raise HTTPException(status_code=422, detail="currency must be ISO-4217 style")
    return cur


def validate_account_type(value: str) -> str:
    kind = str(value or "").strip().lower()
    if kind not in ACCOUNT_TYPES:
        raise HTTPException(status_code=422, detail="invalid budget account type")
    return kind


def row_to_dict(row) -> dict:
    return dict(row) if row is not None else {}
