"""
questions/models.py
====================
Modelos del banco de preguntas.

Diseño de tipos de pregunta:
  El campo 'tipo' determina qué campos adicionales tiene sentido:
    - multiple:  opciones (JSON) + correcta (índice)
    - vf:        correcta_vf (bool)
    - corta:     palabras_clave (JSON list)
    - arrastrar: pares (JSON) + modo_arrastrar (asociar/ordenar)
    - confuso:   sin campos adicionales (reflexión abierta)
    - minuto:    sin campos adicionales (reflexión abierta)
  
  Se usa un único modelo con campos opcionales en lugar de herencia
  por simplicidad de queries y migración.
"""

from django.db import models
from django.conf import settings
from django.core.validators import MinValueValidator, MaxValueValidator

from shared.mixins import TimestampedModel, SoftDeleteModel
from academic.models import Asignatura


class Pregunta(TimestampedModel, SoftDeleteModel):
    """
    Pregunta del banco. Puede ser de múltiples tipos.
    
    Cada tipo tiene sus propios campos opcionales que se populan
    según el tipo seleccionado (el resto quedan null/vacío).
    """

    class Tipo(models.TextChoices):
        MULTIPLE  = 'multiple',  'Selección múltiple'
        VF        = 'vf',        'Verdadero / Falso'
        CORTA     = 'corta',     'Respuesta corta'
        ARRASTRAR = 'arrastrar', 'Arrastrar y soltar'
        CONFUSO   = 'confuso',   'Reflexión: ¿Qué no entendiste?'
        MINUTO    = 'minuto',    'Reflexión: ¿Qué aprendiste?'

    class ModoArrastrar(models.TextChoices):
        ASOCIAR = 'asociar', 'Asociar columnas'
        ORDENAR = 'ordenar', 'Ordenar elementos'

    # ── Metadatos ──
    asignatura = models.ForeignKey(
        Asignatura,
        on_delete=models.CASCADE,
        related_name='preguntas',
        verbose_name='Asignatura'
    )
    docente = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name='preguntas',
        verbose_name='Docente propietario'
    )
    tipo       = models.CharField(max_length=10, choices=Tipo.choices, verbose_name='Tipo')
    enunciado  = models.TextField(verbose_name='Enunciado de la pregunta')
    unidad     = models.CharField(max_length=200, blank=True, verbose_name='Unidad / Tema')
    tiempo_seg = models.PositiveSmallIntegerField(
        default=20,
        validators=[MinValueValidator(5), MaxValueValidator(60)],
        verbose_name='Tiempo de respuesta (segundos)'
    )

    # ── Visibilidad ──
    es_publica = models.BooleanField(
        default=False,
        verbose_name='Pública para otros docentes',
        help_text='Si True, otros docentes pueden ver e importar esta pregunta'
    )
    valoraciones = models.PositiveSmallIntegerField(
        default=0,
        verbose_name='Valoraciones positivas',
        help_text='Votos útiles de otros docentes'
    )

    # ── Campos específicos de tipo: Selección múltiple ──
    # opciones: [{"texto": "...", "correcta": false}, ...]
    opciones = models.JSONField(
        null=True, blank=True,
        verbose_name='Opciones (tipo múltiple)',
        help_text='Lista de objetos {texto, correcta}. Mínimo 2 opciones.'
    )

    # ── Campos específicos: Verdadero/Falso ──
    correcta_vf = models.BooleanField(
        null=True, blank=True,
        verbose_name='Respuesta correcta (V/F)'
    )

    # ── Campos específicos: Respuesta corta ──
    # palabras_clave: ["target", "event.target", "e.target"]
    palabras_clave = models.JSONField(
        null=True, blank=True,
        verbose_name='Palabras clave aceptadas',
        help_text='Lista de strings. Se acepta cualquiera de estas como respuesta válida.'
    )

    # ── Campos específicos: Arrastrar y soltar ──
    # pares: [{"izq": "addEventListener()", "der": "Agregar listener"}, ...]
    # En modo ordenar: solo el campo "izq" tiene valor (el orden correcto)
    pares = models.JSONField(
        null=True, blank=True,
        verbose_name='Pares / elementos (arrastrar)',
        help_text='Lista de objetos {izq, der} para asociar, o {izq} para ordenar.'
    )
    modo_arrastrar = models.CharField(
        max_length=10,
        choices=ModoArrastrar.choices,
        null=True, blank=True,
        verbose_name='Modo de arrastrar'
    )

    class Meta(TimestampedModel.Meta):
        verbose_name = 'Pregunta'
        verbose_name_plural = 'Preguntas'
        db_table = 'questions_pregunta'
        indexes = [
            models.Index(fields=['asignatura', 'tipo']),
            models.Index(fields=['docente', 'es_publica']),
        ]

    def __str__(self):
        return f'[{self.tipo}] {self.enunciado[:60]}...'

    def es_autocalificable(self) -> bool:
        """
        True si la corrección es automática (múltiple, V/F, arrastrar).
        False si requiere revisión del docente (corta, confuso, minuto).
        """
        return self.tipo in (self.Tipo.MULTIPLE, self.Tipo.VF, self.Tipo.ARRASTRAR)


class ImportacionPreguntas(TimestampedModel):
    """
    Registro de cada importación masiva de preguntas desde JSON.
    Sirve para auditar qué se importó, cuándo y con qué resultado.
    """

    docente       = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name='importaciones',
        verbose_name='Docente'
    )
    asignatura    = models.ForeignKey(
        Asignatura,
        on_delete=models.CASCADE,
        related_name='importaciones',
        verbose_name='Asignatura destino'
    )
    archivo_hash  = models.CharField(
        max_length=64,
        verbose_name='Hash SHA-256 del archivo JSON',
        help_text='Para detectar importaciones duplicadas'
    )
    preguntas_ok  = models.PositiveSmallIntegerField(default=0, verbose_name='Preguntas importadas')
    preguntas_err = models.PositiveSmallIntegerField(default=0, verbose_name='Preguntas con error')
    log_errores   = models.TextField(blank=True, verbose_name='Log de errores de validación')

    class Meta(TimestampedModel.Meta):
        verbose_name = 'Importación de preguntas'
        verbose_name_plural = 'Importaciones de preguntas'
        db_table = 'questions_importacion'

    def __str__(self):
        return f'Importación {self.id} — {self.preguntas_ok} OK / {self.preguntas_err} errores'
