from flask_wtf import FlaskForm
from flask_wtf.file import FileField, FileAllowed
from wtforms import StringField, PasswordField, SubmitField, BooleanField, SelectField, DateField, TextAreaField
from wtforms.validators import DataRequired, Length, Email, EqualTo, ValidationError, Optional
from wtforms.widgets import DateInput
from .models import User, Client
from flask_login import current_user
from flask import request

class RegistrationForm(FlaskForm):
    username = StringField('Username', validators=[DataRequired(), Length(min=2, max=20)])
    email = StringField('Email', validators=[DataRequired(), Email()])
    mobile_number = StringField('Mobile Number', validators=[DataRequired(), Length(min=10, max=20)])
    date_of_birth = DateField('Date of Birth', format='%Y-%m-%d', validators=[DataRequired()], widget=DateInput())
    gender = SelectField('Gender', choices=[('Male','Male'),('Female','Female'),('Other','Other'),('Prefer not to say','Prefer not to say')], validators=[DataRequired()])
    password = PasswordField('Password', validators=[DataRequired()])
    confirm_password = PasswordField('Confirm Password', validators=[DataRequired(), EqualTo('password')])
    role = SelectField('Register as', choices=[('user', 'User'), ('consultant', 'Consultant')], validators=[DataRequired()])
    submit = SubmitField('Sign Up')

    def validate_username(self, username):
        user = User.query.filter_by(username=username.data).first()
        if user:
            raise ValidationError('That username is taken. Please choose a different one.')

    def validate_email(self, email):
        user = User.query.filter_by(email=email.data).first()
        if user:
            raise ValidationError('That email is already in use. Please choose a different one.')
    
    def validate_mobile_number(self, mobile_number):
        user = User.query.filter_by(mobile_number=mobile_number.data).first()
        if user:
            raise ValidationError('That mobile number is already in use. Please choose a different one.')

class LoginForm(FlaskForm):
    email = StringField('Email', validators=[DataRequired(), Email()])
    password = PasswordField('Password', validators=[DataRequired()])
    remember = BooleanField('Remember Me')
    submit = SubmitField('Login')

class UpdateProfileForm(FlaskForm):
    username = StringField('Username', validators=[DataRequired(), Length(min=2, max=20)])
    email = StringField('Email', validators=[DataRequired(), Email()])
    mobile_number = StringField('Mobile Number', validators=[DataRequired(), Length(min=10, max=20)])
    submit = SubmitField('Update')

    def validate_username(self, username):
        if username.data != current_user.username:
            user = User.query.filter_by(username=username.data).first()
            if user:
                raise ValidationError('That username is taken. Please choose a different one.')

    def validate_email(self, email):
        if email.data != current_user.email:
            user = User.query.filter_by(email=email.data).first()
            if user:
                raise ValidationError('That email is already in use. Please choose a different one.')
    
    def validate_mobile_number(self, mobile_number):
        if mobile_number.data != current_user.mobile_number:
            user = User.query.filter_by(mobile_number=mobile_number.data).first()
            if user:
                raise ValidationError('That mobile number is already in use. Please choose a different one.')

class ChangePasswordForm(FlaskForm):
    old_password = PasswordField('Current Password', validators=[DataRequired()])
    new_password = PasswordField('New Password', validators=[DataRequired(), Length(min=6)])
    confirm_password = PasswordField('Confirm New Password', validators=[DataRequired(), EqualTo('new_password')])
    submit = SubmitField('Change Password')

class ResetPasswordRequestForm(FlaskForm):
    mobile_number = StringField('Mobile Number', validators=[DataRequired(), Length(min=10, max=20)])
    submit = SubmitField('Request Password Reset')

    def validate_mobile_number(self, mobile_number):
        user = User.query.filter_by(mobile_number=mobile_number.data).first()
        if not user:
            raise ValidationError('No account found with that mobile number.')

class ResetPasswordForm(FlaskForm):
    token = StringField('Reset Token', validators=[DataRequired(), Length(min=10, max=100)])
    new_password = PasswordField('New Password', validators=[DataRequired(), Length(min=6)])
    confirm_password = PasswordField('Confirm New Password', validators=[DataRequired(), EqualTo('new_password')])
    submit = SubmitField('Reset Password')

class ConsultantProfileForm(FlaskForm):
    registration_number = StringField('Registration Number', validators=[DataRequired(), Length(max=100)])
    contact_details = TextAreaField('Contact Details', validators=[DataRequired()])
    logo = FileField('Upload Logo', validators=[FileAllowed(['jpg', 'png', 'jpeg'], 'Images only!')])
    submit = SubmitField('Update Profile')

class CreateClientForm(FlaskForm):
    name = StringField('Name', validators=[DataRequired(), Length(max=100)])
    date_of_birth = DateField('Date of Birth', format='%Y-%m-%d', validators=[DataRequired()], widget=DateInput())
    email = StringField('Email', validators=[Optional(), Email()])
    phone_number = StringField('Phone Number', validators=[Optional(), Length(max=20)])
    center_case_id = StringField('Center Case ID', validators=[DataRequired(), Length(max=64)])
    gender = SelectField('Gender', choices=[('Male', 'Male'), ('Female', 'Female'), ('Other', 'Other')], validators=[DataRequired()])
    referred_by = SelectField('Assigned Consultant', coerce=int, validators=[DataRequired()])
    is_active = BooleanField('Is Active', default='y')
    submit = SubmitField('Create Client')

    def validate_email(self, email):
        if email.data:
            client = Client.query.filter_by(email=email.data).first()
            if client:
                raise ValidationError('That email is already registered to a client. Please use a different one.')
    
    def validate_center_case_id(self, center_case_id):
        from .utils import consultant_prefix, is_alphanumeric
        if not is_alphanumeric(center_case_id.data):
            raise ValidationError('Center Case ID must be alphanumeric.')
        consultant_id = self.referred_by.data
        from .models import User
        consultant = User.query.get(consultant_id) if consultant_id else None
        prefix = consultant_prefix(consultant) if consultant else ''
        if len(center_case_id.data or '') < (len(prefix) + 1) or center_case_id.data[:len(prefix)].upper() != prefix:
            raise ValidationError(f'Center Case ID must start with the consultant prefix "{prefix}".')
        existing = Client.query.filter_by(center_case_id=center_case_id.data).first()
        if existing:
            raise ValidationError('Center Case ID already exists. Please use a unique value.')

class EditClientForm(FlaskForm):
    name = StringField('Name', validators=[DataRequired(), Length(max=100)])
    date_of_birth = DateField('Date of Birth', format='%Y-%m-%d', validators=[DataRequired()], widget=DateInput())
    email = StringField('Email', validators=[Optional(), Email()])
    phone_number = StringField('Phone Number', validators=[Optional(), Length(max=20)])
    center_case_id = StringField('Center Case ID', validators=[DataRequired(), Length(max=64)])
    gender = SelectField('Gender', choices=[('Male', 'Male'), ('Female', 'Female'), ('Other', 'Other')], validators=[DataRequired()])
    referred_by = SelectField('Assigned Consultant', coerce=int, validators=[DataRequired()])
    is_active = BooleanField('Is Active')
    submit = SubmitField('Update Client')

    def validate_email(self, email):
        if email.data:
            client = Client.query.filter_by(email=email.data).first()
            if client and client.id != request.view_args['client_id']:
                raise ValidationError('That email is already registered to another client. Please use a different one.')
    
    def validate_center_case_id(self, center_case_id):
        from .utils import consultant_prefix, is_alphanumeric
        if not is_alphanumeric(center_case_id.data):
            raise ValidationError('Center Case ID must be alphanumeric.')
        consultant_id = self.referred_by.data
        from .models import User
        consultant = User.query.get(consultant_id) if consultant_id else None
        prefix = consultant_prefix(consultant) if consultant else ''
        if len(center_case_id.data or '') < (len(prefix) + 1) or center_case_id.data[:len(prefix)].upper() != prefix:
            raise ValidationError(f'Center Case ID must start with the consultant prefix "{prefix}".')
        existing = Client.query.filter_by(center_case_id=center_case_id.data).first()
        if existing and existing.id != request.view_args['client_id']:
            raise ValidationError('Center Case ID already exists. Please use a unique value.')
