"""
shared/validators/fields.py
============================
Validadores reutilizables para campos de modelos y serializers.
Se aplican con validators=[validate_hex_color] o como campo de form.
"""

import re
import json
import logging
from django.core.exceptions import ValidationError

logger = logging.getLogger('eduplay')


def validate_hex_color(value: str):
    """
    Valida que el valor sea un color hexadecimal válido (#RRGGBB).
    Usado en el campo color de los grupos de alumnos.
    """
    pattern = r'^#[0-9a-fA-F]{6}$'
    if not re.match(pattern, value):
        raise ValidationError(
            f'"{value}" no es un color hexadecimal válido. Usa el formato #RRGGBB.'
        )


def validate_file_size(max_mb: int = 5):
    """
    Factory que retorna un validador de tamaño de archivo.
    Uso: validators=[validate_file_size(max_mb=2)]
    """
    def validator(file):
        size_mb = file.size / (1024 * 1024)
        if size_mb > max_mb:
            raise ValidationError(
                f'El archivo es demasiado grande ({size_mb:.1f} MB). '
                f'El máximo permitido es {max_mb} MB.'
            )
    return validator


def validate_json_question(value: str):
    """
    Valida el formato del JSON de importación de preguntas.
    
    Formato esperado:
    {
        "asignatura_codigo": "TI2031",
        "unidad": "Unidad 3",
        "preguntas": [
            {
                "tipo": "multiple",
                "enunciado": "...",
                "opciones": [...],
                "correcta": 1,
                "tiempo_segundos": 20
            }
        ]
    }
    
    Raises ValidationError con mensaje descriptivo si hay errores.
    """
    TIPOS_VALIDOS = {'multiple', 'vf', 'corta', 'arrastrar', 'confuso', 'minuto'}
    errors = []

    # 1. Verificar que sea JSON válido
    try:
        if isinstance(value, str):
            data = json.loads(value)
        else:
            data = value
    except json.JSONDecodeError as e:
        raise ValidationError(f'JSON inválido: {e}')

    # 2. Verificar campos requeridos en el root
    for campo in ['asignatura_codigo', 'unidad', 'preguntas']:
        if campo not in data:
            errors.append(f'Campo requerido faltante: "{campo}"')

    if errors:
        raise ValidationError(errors)

    # 3. Verificar que preguntas sea una lista no vacía
    if not isinstance(data['preguntas'], list) or len(data['preguntas']) == 0:
        raise ValidationError('"preguntas" debe ser una lista con al menos un elemento')

    # 4. Verificar cada pregunta
    for i, pregunta in enumerate(data['preguntas']):
        prefix = f'Pregunta {i+1}'

        if 'tipo' not in pregunta:
            errors.append(f'{prefix}: falta el campo "tipo"')
            continue

        if pregunta['tipo'] not in TIPOS_VALIDOS:
            errors.append(f'{prefix}: tipo "{pregunta["tipo"]}" no válido. '
                          f'Válidos: {", ".join(TIPOS_VALIDOS)}')

        if 'enunciado' not in pregunta or not pregunta['enunciado'].strip():
            errors.append(f'{prefix}: falta o está vacío el campo "enunciado"')

        if 'tiempo_segundos' in pregunta:
            t = pregunta['tiempo_segundos']
            if not isinstance(t, int) or not (5 <= t <= 60):
                errors.append(f'{prefix}: "tiempo_segundos" debe ser entero entre 5 y 60')

        # Validaciones específicas por tipo
        if pregunta.get('tipo') == 'multiple':
            if 'opciones' not in pregunta or len(pregunta.get('opciones', [])) < 2:
                errors.append(f'{prefix}: tipo "multiple" requiere al menos 2 opciones')
            if 'correcta' not in pregunta:
                errors.append(f'{prefix}: tipo "multiple" requiere campo "correcta" (índice)')

        if pregunta.get('tipo') == 'vf':
            if 'correcta' not in pregunta or not isinstance(pregunta['correcta'], bool):
                errors.append(f'{prefix}: tipo "vf" requiere campo "correcta" (true/false)')

    if errors:
        raise ValidationError(errors)
