"""Enterprise Financial & Arithmetic Precision Utilities.
Strict Rule: No float/double for financial amounts or BoQ quantity calculations.
Uses Decimal(18, 4) arithmetic and standard Vietnamese currency formatting.
"""

from __future__ import annotations

from decimal import ROUND_HALF_UP, Decimal
from typing import Union

NumericType = Union[int, float, str, Decimal]


def to_decimal(val: NumericType | None, default: Decimal = Decimal(0)) -> Decimal:
    """Safely convert any numeric or string value to Decimal with precision preservation."""
    if val is None:
        return default
    if isinstance(val, Decimal):
        return val
    try:
        # Strip currency symbols and whitespace
        s_val = (
            str(val)
            .replace(",", "")
            .replace(" ", "")
            .replace("₫", "")
            .replace("đ", "")
            .strip()
        )
        if not s_val:
            return default
        return Decimal(s_val)
    except Exception:
        return default


def round_currency(val: NumericType | None) -> Decimal:
    """Round to nearest VND integer (0 decimals) per standard Vietnamese accounting."""
    d = to_decimal(val)
    return d.quantize(Decimal(1), rounding=ROUND_HALF_UP)


def round_quantity(val: NumericType | None, places: int = 4) -> Decimal:
    """Round engineering BoQ quantity to specified decimal places (default 4)."""
    d = to_decimal(val)
    target = Decimal(10) ** -places
    return d.quantize(target, rounding=ROUND_HALF_UP)


def format_vnd(val: NumericType | None, show_symbol: bool = True) -> str:
    """Format currency to standard Vietnamese locale with dot thousand separators.
    Example: 123456789 -> '123.456.789 ₫' or '123.456.789'
    """
    d = round_currency(val)
    int_val = int(d)
    formatted = f"{int_val:,}".replace(",", ".")
    return f"{formatted} ₫" if show_symbol else formatted


format_currency = format_vnd


def format_quantity(val: NumericType | None) -> str:
    """Format BoQ quantity cleanly, stripping trailing zeros if whole number."""
    d = to_decimal(val)
    if d == d.to_integral():
        return f"{int(d):,}".replace(",", ".")
    s = f"{d:.4f}".rstrip("0").rstrip(".")
    parts = s.split(".")
    int_part = f"{int(parts[0]):,}".replace(",", ".")
    return f"{int_part},{parts[1]}" if len(parts) > 1 else int_part


def number_to_vietnamese_words(number: NumericType) -> str:
    """Convert integer or decimal VND amount to standard Vietnamese words."""
    d = round_currency(number)
    num = int(d)
    if num == 0:
        return "Không đồng"
    if num < 0:
        return "Âm " + number_to_vietnamese_words(-num)

    digits = ["không", "một", "hai", "ba", "bốn", "năm", "sáu", "bảy", "tám", "chín"]
    units = ["", "nghìn", "triệu", "tỷ", "nghìn tỷ", "triệu tỷ"]

    def read_three_digits(n: int, is_highest: bool = False) -> str:
        h = n // 100
        t = (n % 100) // 10
        u = n % 10
        res = []

        if h > 0 or not is_highest:
            res.append(digits[h] + " trăm")

        if t > 1:
            res.append(digits[t] + " mươi")
            if u == 1:
                res.append("mốt")
            elif u == 5:
                res.append("lăm")
            elif u > 0:
                res.append(digits[u])
        elif t == 1:
            res.append("mười")
            if u == 5:
                res.append("lăm")
            elif u > 0:
                res.append(digits[u])
        elif t == 0:
            if u > 0:
                if h > 0 or not is_highest:
                    res.append("lẻ " + digits[u])
                else:
                    res.append(digits[u])

        return " ".join(res)

    groups = []
    temp = num
    while temp > 0:
        groups.append(temp % 1000)
        temp //= 1000

    result_words = []
    for idx, grp in enumerate(groups):
        if grp > 0:
            is_highest = idx == len(groups) - 1
            words = read_three_digits(grp, is_highest)
            unit = units[idx]
            if unit:
                result_words.append(f"{words} {unit}")
            else:
                result_words.append(words)

    full_str = " ".join(reversed(result_words)).strip()
    full_str = full_str[0].upper() + full_str[1:] + " đồng chẵn."
    return full_str
