from flask_wtf import FlaskForm # type: ignore
from wtforms import StringField, PasswordField, SubmitField, TextAreaField, IntegerField, SelectField
from wtforms.validators import DataRequired, EqualTo, Length, ValidationError, NumberRange, Optional, InputRequired # type: ignore
from models import User, Odi, Ano, Trimestre, Rango, OdiPersonal, Rol, Localizacion, DivisionesGenerales, Unidades, GerenciasGenerales, Coordinaciones
from config import ADMIN_ROLE_ID, GERENTE_ROLE_ID, SUPERVISOR_ROLE_ID, EVALUADO_ROLE_ID # type: ignore
 
class LoginForm(FlaskForm):
    username = StringField('Usuario', validators=[DataRequired(), Length(min=2, max=10)])
    password = PasswordField('Contraseña', validators=[DataRequired()])
    submit = SubmitField('Iniciar Sesión')

class OdiForm(FlaskForm):
    descripcion = TextAreaField('Descripción del ODI', validators=[DataRequired(), Length(max=500)]) # Max length for description
    peso = IntegerField('Peso (Valor numérico)', validators=[DataRequired(), NumberRange(min=1, max=100)]) # Assuming weight is 1-100
    submit = SubmitField('Guardar ODI')

class AssignOdiForm(FlaskForm):
    id_ano = SelectField('Año', validators=[DataRequired()], coerce=int)
    id_trimestre = SelectField('Trimestre', validators=[DataRequired()], coerce=int)
    personal_id = SelectField('Evaluado', validators=[DataRequired()], coerce=str)
    submit = SubmitField('Asignar ODIs/Competencias')

    def __init__(self, *args, **kwargs):
        super(AssignOdiForm, self).__init__(*args, **kwargs)
        # Populate choices dynamically in the route or here if fixed
        self.id_ano.choices = [(0, '--- Año ---')] + [(a.id_ano, a.descripcion) for a in Ano.query.order_by(Ano.descripcion.desc()).all()]
        self.id_trimestre.choices = [(0, '--- Trimestre ---')] + [(s.id_trimestre, s.descripcion) for s in Trimestre.query.order_by(Trimestre.id_trimestre).all()]
        # Filter evaluados (role ID 4) and active users (estatu=True)
        self.personal_id.choices = [(0, '--- Seleccionar Evaluado ---')] + \
                                    [(u.id_personal, u.full_name) for u in User.query.filter_by(id_rol=EVALUADO_ROLE_ID, estatu=True).order_by(User.nombre).all()]
'''
class AdminUserEditForm(FlaskForm):
    nombre = StringField('Nombre', validators=[DataRequired(), Length(max=100)])
    apellido = StringField('Apellido', validators=[DataRequired(), Length(max=100)])
    cedula = IntegerField('Cédula', validators=[DataRequired()])
    nacionalidad = SelectField('Nacionalidad', choices=[('V', 'Venezolana'), ('E', 'Extranjera')], validators=[DataRequired()])
    usuario = StringField('Usuario', validators=[DataRequired(), Length(min=2, max=10)])
    id_rol = SelectField('Rol', coerce=int, validators=[DataRequired()])
    estatu = SelectField('Estado', choices=[(True, 'Activo'), (False, 'Inactivo')], coerce=bool, validators=[DataRequired()])
    submit = SubmitField('Actualizar Usuario')

    def __init__(self, original_username, *args, **kwargs):
        super(AdminUserEditForm, self).__init__(*args, **kwargs)
        self.original_username = original_username

    def validate_usuario(self, usuario):
        if usuario.data != self.original_username:
            user = User.query.filter_by(usuario=usuario.data).first()
            if user:
                raise ValidationError('Ese nombre de usuario ya está tomado. Por favor, elige uno diferente.')
'''

class EditUserForm(FlaskForm):
    # Non-editable fields - these are for display only, not part of the form submission
    # We will pass the user object directly to the template for these.
    # We will NOT define these as form fields here because we don't want them submitted/validated.

    # Editable Fields:

    # Password Field - Optional, only required if user types something
    password = PasswordField(
        'Nueva Contraseña',
        validators=[
            Optional(), # Password is optional for editing
            Length(min=6, message='La contraseña debe tener al menos 6 caracteres.')
        ],
        description='Dejar en blanco para mantener la contraseña actual.'
    )
    confirm_password = PasswordField(
        'Confirmar Nueva Contraseña',
        validators=[
            EqualTo('password', message='Las contraseñas deben coincidir.'),
            Optional() # This must also be optional if password is
        ]
    )

    # Estatu Field (Status) - Use SelectField for 'Activo' / 'Inactivo'
    estatu = SelectField(
        'Estatus del Usuario',
        choices=[('True', 'Activo'), ('False', 'Inactivo')], # Values will be strings 'True'/'False'
        validators=[InputRequired()]
    )

    # Rol Field (Role) - Dynamically populated
    id_rol = SelectField(
        'Rol del Usuario',
        validators=[DataRequired()],
        coerce=int # Convert selected value to integer (id_rol)
    )

    submit = SubmitField('Actualizar Usuario')

    # Custom validator to populate rol choices dynamically
    def __init__(self, *args, **kwargs):
        super(EditUserForm, self).__init__(*args, **kwargs)
        from app import app
        with app.app_context(): # Ensure we are within an app context to query the database
            roles = Rol.query.all()
            self.id_rol.choices = [(role.id_rol, role.descripcion) for role in roles]

class SearchUserByCedulaForm(FlaskForm):
    cedula = IntegerField('Cédula del Evaluado', validators=[DataRequired(), NumberRange(min=1, message="Cédula debe ser un número válido.")])
    submit = SubmitField('Buscar Evaluado')

# Form to assign/edit UbicacionPersonal
class AssignLocationForm(FlaskForm):

    # Role field
    id_rol = SelectField(
        'Rol del Usuario',
        coerce=int,
        validators=[]
    )

    # Level 0 — always required
    id_localizacion = SelectField(
        'Localización',
        validators=[DataRequired()],
        coerce=int
    )

    # Levels 1–4 — only required when id_localizacion == 1 (sede)
    # Validation is handled client-side + server-side in the route
    id_divisiones_generales = SelectField(
        'Dirección',
        validators=[Optional()],
        coerce=int
    )
    id_unidades = SelectField(
        'Gerencia General',
        validators=[Optional()],
        coerce=int
    )
    id_gerencias_generales = SelectField(
        'Gerencia de Línea',
        validators=[Optional()],
        coerce=int
    )
    id_coordinaciones = SelectField(
        'Coordinación',
        validators=[Optional()],
        coerce=int
    )

    submit = SubmitField('Asignar Ubicación y Rol')

    def __init__(self, *args, **kwargs):
        super(AssignLocationForm, self).__init__(*args, **kwargs)
        from app import app
        with app.app_context():
            # Pre-populate Localizacion (always visible)
            loc_choices = [(0, '--- Seleccionar Localización ---')]
            loc_choices.extend([
                (l.id_localizacion, l.nombre)
                for l in Localizacion.query.filter_by(valido=True).order_by(Localizacion.id_localizacion).all()
            ])
            self.id_localizacion.choices = loc_choices

            # Pre-populate DivisionesGenerales (always pre-loaded, shown/hidden by JS)
            div_choices = [(0, '--- Seleccionar Dirección ---')]
            div_choices.extend([
                (d.id_divisiones_generales, d.nombre)
                for d in DivisionesGenerales.query.filter_by(valido=True).order_by(DivisionesGenerales.id_divisiones_generales).all()
            ])
            self.id_divisiones_generales.choices = div_choices

            # Cascading levels start empty (populated via AJAX)
            self.id_unidades.choices = [(0, '--- Seleccionar Gerencia General ---')]
            self.id_gerencias_generales.choices = [(0, '--- Seleccionar Gerencia de Línea ---')]
            self.id_coordinaciones.choices = [(0, '--- Seleccionar Coordinación ---')]

class AssignCursosForm(FlaskForm):
    # These will be dynamically populated in the route
    id_ano = SelectField('Año', coerce=int, validators=[DataRequired()])
    id_trimestre = SelectField('Trimestre', coerce=int, validators=[DataRequired()])
    personal_id = SelectField('Evaluado', coerce=int, validators=[DataRequired()])
    submit = SubmitField('Guardar Cursos')

class TalentoHumanoObservationForm(FlaskForm):
    observacion_th = TextAreaField('Observación de Talento Humano', validators=[DataRequired(), Length(min=1, max=500)])
    submit = SubmitField('Guardar Observación')

class ChangePasswordForm(FlaskForm):
    password = PasswordField(
        'Nueva Contraseña', 
        validators=[DataRequired(), Length(min=6, message='La contraseña debe tener al menos 6 caracteres.')], 
        description='Mínimo 6 caracteres.'
    )
    confirm_password = PasswordField(
        'Confirmar Contraseña', 
        validators=[DataRequired(), EqualTo('password', message='Las contraseñas deben coincidir.')]
    )
    submit = SubmitField('Cambiar Contraseña')    