#!/usr/bin/env python3
import decimal
import re


def cdedbid(persona_id: str | int) -> str:
    """Turn a raw persona_id into a formatted id, including checkdigit."""
    digits = []
    tmp = int(persona_id)
    while tmp > 0:
        digits.append(tmp % 10)
        tmp = tmp // 10
    dsum = sum((i + 2) * d for i, d in enumerate(digits))
    return f"DB-{persona_id}-{'0123456789X'[-dsum % 11]}"


CDEDB_PATTERN = re.compile(r"DB-(?P<persona_id>[0-9]+)-(?P<checkdigit>[0-9X])", flags=re.I)


def parse_id(id_: str) -> int | None:
    """Pars a CdEDB-ID or persona_id into a raw persona_id."""
    id_ = (id_ or "").strip()
    if not id_:
        return None
    try:
        return int(id_)
    except ValueError:
        if match := CDEDB_PATTERN.fullmatch(id_):
            persona_id, checkdigit = match.groups()
            if id_ == cdedbid(persona_id):
                return int(persona_id)
        raise


def parse_amount(raw: str) -> decimal.Decimal | None:
    """Parse a raw amount into Decimal. Strip any '€' symbols or whitespace. Handle both ',' and '.' decimal separators."""
    if not raw:
        return None
    if raw.startswith("(") and raw.endswith(")"):
        raw = f"-{raw[1:-1]}"
    raw_amount = raw.strip().rstrip(" €")
    try:
        amount = decimal.Decimal(raw_amount)
    except decimal.DecimalException:
        try:
            amount = decimal.Decimal(raw_amount.replace(",", "."))
        except decimal.DecimalException:
            return None
    return amount
