from decimal import Decimal, InvalidOperation, ROUND_HALF_UP

from django.conf import settings


AMOUNT_MODE_HAOBUYE_INTEGER = 'haobuye_integer_round_half_up'
AMOUNT_MODE_STANDARD_DECIMAL_2 = 'standard_decimal_2'
AMOUNT_MODES = {
    AMOUNT_MODE_HAOBUYE_INTEGER,
    AMOUNT_MODE_STANDARD_DECIMAL_2,
}
INTEGER_QUANT = Decimal('1')
DECIMAL_2_QUANT = Decimal('0.01')


def to_decimal(value, *, field_name: str = 'value') -> Decimal:
    try:
        return Decimal(str(value))
    except (InvalidOperation, TypeError, ValueError) as exc:
        raise ValueError(f'{field_name} 必须是数字') from exc


def normalize_money_amount(value, *, field_name: str = 'amount') -> Decimal:
    decimal_value = to_decimal(value, field_name=field_name)
    return decimal_value.quantize(_money_quant(), rounding=ROUND_HALF_UP)


def calculate_line_amount(*, quantity, price, standard_quantity=None) -> Decimal:
    raw_quantity = quantity
    if _amount_mode() == AMOUNT_MODE_STANDARD_DECIMAL_2 and standard_quantity is not None:
        raw_quantity = standard_quantity

    quantity_value = to_decimal(
        raw_quantity,
        field_name='quantity',
    )
    price_value = to_decimal(price, field_name='price')
    return (quantity_value * price_value).quantize(_money_quant(), rounding=ROUND_HALF_UP)


def calculate_settlement_amount(*, amount, discount_amount=Decimal('0')) -> Decimal:
    return normalize_money_amount(
        normalize_money_amount(amount, field_name='amount')
        + normalize_money_amount(discount_amount or Decimal('0'), field_name='discount_amount'),
        field_name='settlement_amount',
    )


def _amount_mode() -> str:
    mode = getattr(settings, 'BUSINESS_AMOUNT_MODE', AMOUNT_MODE_HAOBUYE_INTEGER)
    if mode not in AMOUNT_MODES:
        raise ValueError(f'BUSINESS_AMOUNT_MODE 不合法: {mode}')
    return mode


def _money_quant() -> Decimal:
    if _amount_mode() == AMOUNT_MODE_STANDARD_DECIMAL_2:
        return DECIMAL_2_QUANT
    return INTEGER_QUANT
