import uuid
import datetime
import re

class GeneradorIDUnico:
    def __init__(self, tipo_objeto: str):
        if not re.match(r'^[A-Z]{4}$', tipo_objeto):
            raise ValueError("El tipo de objeto debe tener 4 letras en mayúscula (ej: ABCD)")
        self.tipo_objeto = tipo_objeto

    def generar(self):
        f = datetime.datetime.now().strftime('%Y%m%d')
        u = uuid.uuid4().hex[:9]
        n = ''.join(filter(str.isdigit, uuid.uuid4().hex))[:8]
        n = n.ljust(8, '0')
        t = sum(int(c) for c in f)
        t += sum(int(c, 16) for c in u)
        t += sum(int(c) for c in n)
        c = str(t % 10)
        l = t + int(c)
        d = hex(l % 16)[-1]

        return f"{self.tipo_objeto}{f}-{d}{u}{c}{n}"


    @staticmethod
    def verificar(id_: str) -> bool:
        try:
            f = id_[4:12]
            cuerpo = id_[13:]
            d = cuerpo[0]
            u = cuerpo[1:10]
            c = cuerpo[10]
            n = cuerpo[11:19]
            t = sum(int(c) for c in f)
            t += sum(int(c, 16) for c in u)
            t += sum(int(c) for c in n)
            esd = str(t % 10)
            l = t + int(esd)
            esh = hex(l % 16)[-1]
            return (
                d.lower() == esh.lower() and
                c == esd
            )
        except Exception:
            return False

    @staticmethod
    def tamaño_bytes_bits(id_: str):
        """Devuelve el tamaño del ID en bytes y bits (UTF-8)"""
        bytes_ = len(id_.encode('utf-8'))
        return bytes_, bytes_ * 8


if __name__ == "__main__":
    # Ejemplo de uso
    generador = GeneradorIDUnico("FACT")
    nuevo_id = generador.generar()
    print(f"Nuevo ID generado: {nuevo_id}")

    # Verificación del ID
    es_valido = GeneradorIDUnico.verificar(nuevo_id)
    print(f"El ID es válido: {es_valido}")

    # Tamaño del ID
    bytes_, bits_ = GeneradorIDUnico.tamaño_bytes_bits(nuevo_id)
    print(f"Tamaño del ID: {bytes_} bytes / {bits_} bits")
