"""
app/forms.py – Formularios WTForms con validaciones.
"""
from datetime import date
from flask_wtf import FlaskForm
from flask_wtf.file import FileField, FileAllowed
from wtforms import (StringField, PasswordField, SelectField, TextAreaField,
                     IntegerField, DateField, BooleanField, RadioField,
                     SubmitField, SelectMultipleField)
from wtforms.validators import (DataRequired, InputRequired, Email, Length,
                                 Optional, NumberRange, EqualTo, ValidationError)


# ---------------------------------------------------------------
# Autenticación
# ---------------------------------------------------------------
class LoginForm(FlaskForm):
    correo     = StringField('Correo electrónico',
                             validators=[DataRequired(), Email(), Length(max=150)])
    password   = PasswordField('Contraseña', validators=[DataRequired()])
    submit     = SubmitField('Iniciar sesión')


# ---------------------------------------------------------------
# Usuarios
# ---------------------------------------------------------------
class UsuarioForm(FlaskForm):
    nombre_completo = StringField('Nombre completo',
                                  validators=[DataRequired(), Length(max=150)])
    correo          = StringField('Correo electrónico',
                                  validators=[DataRequired(), Email(), Length(max=150)])
    password        = PasswordField('Contraseña (dejar vacío para no cambiar)',
                                    validators=[Optional(), Length(min=6, max=128)])
    password2       = PasswordField('Confirmar contraseña',
                                    validators=[Optional(), EqualTo('password',
                                                message='Las contraseñas no coinciden.')])
    puesto          = StringField('Puesto', validators=[DataRequired(), Length(max=100)])
    rol_id          = SelectField('Rol', coerce=int, validators=[DataRequired()])
    activo          = BooleanField('Usuario activo', default=True)
    submit          = SubmitField('Guardar')


# ---------------------------------------------------------------
# Sistemas
# ---------------------------------------------------------------
class SistemaForm(FlaskForm):
    nombre      = StringField('Nombre del sistema',
                              validators=[DataRequired(), Length(max=150)])
    descripcion = TextAreaField('Descripción', validators=[Optional()])
    activo      = BooleanField('Sistema activo', default=True)
    submit      = SubmitField('Guardar')


# ---------------------------------------------------------------
# Relación usuario-sistema
# ---------------------------------------------------------------
class RelacionForm(FlaskForm):
    sistema_id  = SelectField('Sistema', coerce=int, validators=[DataRequired()])
    usuario_ids = SelectMultipleField('Usuarios asignados', coerce=int)
    submit      = SubmitField('Guardar asignación')


# ---------------------------------------------------------------
# Transacción 1: Alta de Cambio
# ---------------------------------------------------------------
class AltaCambioForm(FlaskForm):
    sistema_id             = SelectField('Sistema a Modificar', coerce=int,
                                         validators=[DataRequired()])
    usuario_solicitante_id = SelectField('Usuario Solicitante', coerce=int,
                                          validators=[DataRequired()])
    numero_incidencia      = IntegerField('Número de Incidencia',
                                          validators=[InputRequired(),
                                                      NumberRange(min=0)])
    descripcion_breve      = TextAreaField('Descripción Breve',
                                           validators=[DataRequired()])
    urgente                = RadioField('Urgencia',
                                        choices=[('0', 'No Urgente'), ('1', 'Urgente')],
                                        default='0')
    fecha_pruebas          = DateField('Fecha de Pruebas',
                                       validators=[DataRequired()])
    submit                 = SubmitField('Registrar Solicitud')

    def validate_fecha_pruebas(self, field):
        if not field.data:
            return
        es_urgente = self.urgente.data == '1'
        if es_urgente and field.data < date.today():
            raise ValidationError('Para cambios urgentes la fecha no puede ser anterior a hoy.')
        if not es_urgente and field.data <= date.today():
            raise ValidationError('Para cambios no urgentes la fecha debe ser posterior a hoy.')


# ---------------------------------------------------------------
# Transacción 2: Aplicación de Cambio
# ---------------------------------------------------------------
class AplicacionCambioForm(FlaskForm):
    descripcion_tecnica        = TextAreaField('Descripción Técnica del Cambio',
                                               validators=[DataRequired()])
    fecha_propuesta_produccion = DateField('Fecha Propuesta de Aplicación a Producción',
                                           validators=[DataRequired()])
    archivo_cambio             = FileField('Archivo de Objetos/Scripts (ZIP o SQL)',
                                           validators=[
                                               Optional(),
                                               FileAllowed(['zip', 'sql'],
                                                           'Solo se permiten archivos ZIP o SQL.')
                                           ])
    submit                     = SubmitField('Guardar Aplicación')

    def validate_fecha_propuesta_produccion(self, field):
        # La validación con fecha_pruebas se hace en la ruta (requiere el objeto cambio)
        if field.data and field.data < date.today():
            raise ValidationError('La fecha propuesta no puede ser anterior a hoy.')


# ---------------------------------------------------------------
# Transacción 3: Liberación a Producción
# ---------------------------------------------------------------
class LiberacionCambioForm(FlaskForm):
    fecha_real_aplicacion = DateField('Fecha Real de Aplicación',
                                      validators=[DataRequired()])
    usuario_valido_id     = SelectField('Usuario que Validó en Producción', coerce=int,
                                         validators=[DataRequired()])
    estado_cambio         = SelectField('Estado del Cambio',
                                        choices=[
                                            ('', '-- Seleccionar --'),
                                            ('Cambio Correcto', 'Cambio Correcto'),
                                            ('Cambio Incorrecto', 'Cambio Incorrecto'),
                                        ],
                                        validators=[DataRequired()])
    observaciones         = TextAreaField('Observaciones', validators=[Optional()])
    submit                = SubmitField('Liberar a Producción')


# ---------------------------------------------------------------
# Filtros para reporte de listado
# ---------------------------------------------------------------
class FiltrosReporteForm(FlaskForm):
    fecha_desde         = DateField('Fecha desde', validators=[Optional()])
    fecha_hasta         = DateField('Fecha hasta', validators=[Optional()])
    sistema_id          = SelectField('Sistema', coerce=int, validators=[Optional()])
    estatus             = SelectField('Estatus',
                                     choices=[
                                         (0, 'Todos'),
                                         ('Solicitado',  'Solicitado'),
                                         ('Programado',  'Programado'),
                                         ('Liberado',    'Liberado'),
                                     ],
                                     validators=[Optional()])
    usuario_solicitante = SelectField('Usuario Solicitante', coerce=int,
                                      validators=[Optional()])
    submit              = SubmitField('Generar PDF')
