from ..core.base import BaseValidator

class RUT(BaseValidator):
    """
    Validator for Chilean RUT (Rol Único Tributario).
    """

    @classmethod
    def clean(cls, doc: str) -> str:
        return doc.upper().replace('.', '').replace('-', '').replace(' ', '')

    @classmethod
    def validate(cls, doc: str) -> bool:
        # Clean but keep 'K' if present
        doc = cls.clean(doc)
        
        if len(doc) < 2:
            return False
            
        body = doc[:-1]
        dv = doc[-1]
        
        if not body.isdigit():
            return False
            
        # Calculate DV
        # Reverse body
        reversed_body = body[::-1]
        
        # Factors: 2, 3, 4, 5, 6, 7, 2, 3...
        factors = [2, 3, 4, 5, 6, 7]
        
        sum_val = 0
        for i, digit in enumerate(reversed_body):
            sum_val += int(digit) * factors[i % 6]
            
        remainder = sum_val % 11
        result = 11 - remainder
        
        if result == 11:
            calculated_dv = '0'
        elif result == 10:
            calculated_dv = 'K'
        else:
            calculated_dv = str(result)
            
        return dv == calculated_dv

    @classmethod
    def format(cls, doc: str) -> str:
        doc = cls.clean(doc)
        if len(doc) < 2:
            raise ValueError("Invalid RUT length")
            
        body = doc[:-1]
        dv = doc[-1]
        
        # Add dots
        formatted_body = ""
        for i, digit in enumerate(body[::-1]):
            if i > 0 and i % 3 == 0:
                formatted_body = "." + formatted_body
            formatted_body = digit + formatted_body
            
        return f"{formatted_body}-{dv}"

    @classmethod
    def generate(cls) -> str:
        """Generates a valid RUT."""
        import random
        # 7 or 8 digits
        body = "".join([str(random.randint(0, 9)) for _ in range(random.randint(7, 8))])
        
        reversed_body = body[::-1]
        multiplier = 2
        total = 0
        for digit in reversed_body:
            total += int(digit) * multiplier
            multiplier += 1
            if multiplier > 7:
                multiplier = 2
                
        remainder = total % 11
        dv = 11 - remainder
        if dv == 11: dv_char = '0'
        elif dv == 10: dv_char = 'K'
        else: dv_char = str(dv)
        
        return cls.format(body + dv_char)
