from ..core.base import BaseValidator

class TituloEleitor(BaseValidator):
    """
    Validator for Brazilian Voter ID (Título de Eleitor).
    """

    @classmethod
    def validate(cls, doc: str) -> bool:
        doc = cls.clean(doc)
        
        if len(doc) != 12:
            return False
            
        # Validate UF (digits 9 and 10)
        uf_code = int(doc[8:10])
        if not (1 <= uf_code <= 28):
            return False

        # First digit (DV1)
        # Weights 2 to 9 for first 8 digits
        sum_val = 0
        for i in range(8):
            sum_val += int(doc[i]) * (i + 2) # Weights: 2, 3, 4, 5, 6, 7, 8, 9
            
        remainder = sum_val % 11
        digit1 = 0 if remainder == 10 else remainder
        
        # SP/MG exception for DV1? 
        # Standard rule: if remainder is 0, check UF. 
        # Actually, the general rule is: remainder 10 -> 0.
        # But if UF is SP (01) or MG (02) and remainder is 0, does it change?
        # Research says: if remainder is 0, digit is 0. If remainder is 1, digit is 1? No.
        # Let's stick to the standard modulo 11 described in research.
        # Research: "Se o resto for 10, o DV1 calculado é 0. Caso contrário, o DV1 calculado é o próprio resto."
        
        if int(doc[10]) != digit1:
            return False

        # Second digit (DV2)
        # Weights 7, 8, 9 for UF digits and DV1
        # Digits at indices 8, 9, 10
        sum_val = int(doc[8]) * 7 + int(doc[9]) * 8 + int(doc[10]) * 9
        
        remainder = sum_val % 11
        digit2 = 0 if remainder == 10 else remainder

        return int(doc[11]) == digit2

    @classmethod
    def format(cls, doc: str) -> str:
        doc = cls.clean(doc)
        if len(doc) != 12:
            raise ValueError("Título de Eleitor must have 12 digits")
        return f"{doc[:4]} {doc[4:8]} {doc[8:12]}"
