from ..core.base import BaseValidator
import random

class CNPJ(BaseValidator):
    """
    Validator for Brazilian CNPJ (Cadastro Nacional da Pessoa Jurídica).
    """

    @classmethod
    def validate(cls, doc: str) -> bool:
        doc = cls.clean(doc)
        
        if len(doc) != 14:
            return False
            
        if doc == doc[0] * 14:
            return False

        # First digit
        weights1 = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]
        sum_val = sum(int(doc[i]) * weights1[i] for i in range(12))
        remainder = sum_val % 11
        digit1 = 0 if remainder < 2 else 11 - remainder

        if int(doc[12]) != digit1:
            return False

        # Second digit
        weights2 = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]
        sum_val = sum(int(doc[i]) * weights2[i] for i in range(13))
        remainder = sum_val % 11
        digit2 = 0 if remainder < 2 else 11 - remainder

        return int(doc[13]) == digit2

    @classmethod
    def format(cls, doc: str) -> str:
        doc = cls.clean(doc)
        if len(doc) != 14:
            raise ValueError("CNPJ must have 14 digits")
        return f"{doc[:2]}.{doc[2:5]}.{doc[5:8]}/{doc[8:12]}-{doc[12:]}"

    @classmethod
    def generate(cls, formatted: bool = True) -> str:
        """Generates a valid random CNPJ."""
        digits = [random.randint(0, 9) for _ in range(8)] + [0, 0, 0, 1] # Common root
        
        # First digit
        weights1 = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]
        sum_val = sum(d * weights1[i] for i, d in enumerate(digits))
        remainder = sum_val % 11
        digit1 = 0 if remainder < 2 else 11 - remainder
        digits.append(digit1)
        
        # Second digit
        weights2 = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]
        sum_val = sum(d * weights2[i] for i, d in enumerate(digits))
        remainder = sum_val % 11
        digit2 = 0 if remainder < 2 else 11 - remainder
        digits.append(digit2)
        
        cnpj = "".join(map(str, digits))
        return cls.format(cnpj) if formatted else cnpj
