from __future__ import annotations

import datetime as _dt

from .utils import left_zero, to_aaaammdd


def calcular_digito_verificador(cdc: str, base_max: int = 11) -> int:
    v_total = 0
    k = 2

    v_numero_al = ""
    for ch in cdc:
        up = ch.upper()
        if not ("0" <= up <= "9"):
            v_numero_al += str(ord(up))
        else:
            v_numero_al += up

    for i in range(len(v_numero_al) - 1, -1, -1):
        if k > base_max:
            k = 2
        v_numero_aux = int(v_numero_al[i : i + 1])
        v_total += v_numero_aux * k
        k += 1

    v_resto = v_total % 11
    if v_resto > 1:
        return 11 - v_resto
    return 0


def generate_cdc(params: dict, data: dict, codigo_seguridad: str) -> str:
    ruc = params.get("ruc")
    if not ruc or "-" not in str(ruc):
        raise ValueError("RUC debe contener dígito verificador en params.ruc")

    tipo_documento = data["tipoDocumento"]

    ruc_emisor = str(ruc).split("-")[0]
    ruc_emisor = left_zero(ruc_emisor, 8)

    dv_emisor = str(ruc).split("-")[1]
    establecimiento = left_zero(data["establecimiento"], 3)
    punto = left_zero(data["punto"], 3)
    numero = left_zero(data["numero"], 7)
    tipo_contribuyente = str(params.get("tipoContribuyente") or "1")

    fecha_val = data["fecha"]
    if isinstance(fecha_val, str):
        # Handle space or T
        fecha_val = fecha_val.replace(" ", "T")
        fecha_dt = _dt.datetime.fromisoformat(fecha_val[:19])
    elif isinstance(fecha_val, _dt.datetime):
        fecha_dt = fecha_val
    else:
        raise ValueError("data.fecha debe ser ISO string o datetime")

    fecha_emision = to_aaaammdd(fecha_dt)
    tipo_emision = str(data.get("tipoEmision") or "1")

    cdc = (
        left_zero(tipo_documento, 2)
        + ruc_emisor
        + dv_emisor
        + establecimiento
        + punto
        + numero
        + tipo_contribuyente
        + fecha_emision
        + tipo_emision
        + str(codigo_seguridad)
    )

    dv = calcular_digito_verificador(cdc, 11)
    return cdc + str(dv)
