from flask import Blueprint, render_template, redirect, url_for, request, flash, current_app
from flask_login import login_user, logout_user, login_required, current_user
from app.forms import LoginForm, RegistrationForm, RequestPasswordResetForm, ResetPasswordForm
from app import create_app, db
from app import limiter
from datetime import datetime, timezone
from app.config import ALLOWED_EMAILS
import logging
from flask_mail import Message
from app import mail
from app.models import User

bp = Blueprint('auth', __name__)
logger = logging.getLogger(__name__)

@bp.route('/login', methods=['GET', 'POST'])
@limiter.limit("5 per minute")
def login():
    if current_user.is_authenticated:
        return redirect(url_for('main.calculator'))
    
    form = LoginForm()
    if form.validate_on_submit():
        try:
            email = form.email.data.strip().lower()
            password = form.password.data
            
            # Log the login attempt
            current_app.logger.info(f'Login attempt for email: {email}')
            
            user = User.authenticate(email, password)
            if user:
                login_user(user, remember=form.remember_me.data)
                user.last_login = datetime.now(timezone.utc)
                db.session.commit()
                current_app.logger.info(f'User {user.email} logged in successfully')
                next_page = request.args.get('next') or url_for('main.calculator')
                return redirect(next_page)
            else:
                current_app.logger.warning(f'Failed login attempt for email: {email}')
                flash('Invalid email or password', 'danger')
        except Exception as e:
            current_app.logger.error(f'Login error: {str(e)}', exc_info=True)
            flash('An error occurred during login. Please try again.', 'danger')
    
    return render_template('auth/login.html', form=form)

@bp.route('/register', methods=['GET', 'POST'])
@limiter.limit(lambda: None if current_app.config.get('DEBUG', False) else "10 per hour")
def register():
    try:
        if current_user.is_authenticated:
            return redirect(url_for('main.home'))
        
        form = RegistrationForm()
        logger.info('Registration form initialized')
        
        if form.validate_on_submit():
            try:
                email = form.email.data.strip().lower()
                username = form.username.data.strip().lower()
                company = form.company.data.strip().upper()
                logger.info(f'Processing registration for email: {email}, username: {username}, company: {company}')
                
                # Check if email is in allowed list or has adidas.com domain
                if email not in ALLOWED_EMAILS and not email.endswith('@adidas.com'):
                    logger.warning(f'Registration attempt with non-allowed email: {email}')
                    flash('Registration is not allowed for this email domain', 'danger')
                    return render_template('auth/register.html', form=form)
                    
                try:
                    logger.info('Creating new user...')
                    user = User.create(
                        username=username,
                        email=email,
                        company=company,
                        password=form.password.data
                    )
                    logger.info('User created, committing to database...')
                    db.session.commit()
                    logger.info(f'New user registered successfully: {user.email}')
                    flash('Registration successful! Please login', 'success')
                    return redirect(url_for('auth.login'))
                except ValueError as e:
                    logger.warning(f'Registration validation error: {str(e)}')
                    flash(str(e), 'danger')
                except Exception as e:
                    db.session.rollback()
                    logger.error(f'Registration error: {str(e)}', exc_info=True)
                    flash('An error occurred during registration', 'danger')
            except Exception as e:
                logger.error(f'Unexpected error during registration: {str(e)}', exc_info=True)
                flash('An unexpected error occurred', 'danger')
        elif form.errors:
            logger.warning(f'Form validation errors: {form.errors}')
            for field, errors in form.errors.items():
                for error in errors:
                    flash(f'{field}: {error}', 'danger')
                    logger.warning(f'Field {field} validation error: {error}')
        
        logger.info('Rendering registration template')
        return render_template('auth/register.html', form=form)
    except Exception as e:
        logger.error(f'Critical error in registration route: {str(e)}', exc_info=True)
        flash('A critical error occurred', 'danger')
        return render_template('auth/register.html', form=form)

@bp.route('/logout')
@login_required
def logout():
    current_app.logger.info(f'User {current_user.email} logged out')
    logout_user()
    flash('You have been logged out.', 'info')
    return redirect(url_for('main.home'))

@bp.route('/request-reset', methods=['GET', 'POST'])
@limiter.limit("3 per hour")
def request_reset():
    if current_user.is_authenticated:
        return redirect(url_for('main.calculator'))
    
    form = RequestPasswordResetForm()
    if form.validate_on_submit():
        try:
            email = form.email.data.strip().lower()
            user = User.query.filter_by(email=email).first()
            
            if user:
                token = user.generate_reset_token()
                db.session.commit()
                
                reset_url = url_for('auth.reset_password', token=token, _external=True)
                flash(f'Your password reset link is: {reset_url}', 'info')
                flash('This link will expire in 15 minutes.', 'warning')
                return redirect(url_for('auth.login'))
            
            # Always show success message to prevent email enumeration
            flash('If an account exists with that email, you will receive password reset instructions.', 'info')
            return redirect(url_for('auth.login'))
            
        except Exception as e:
            current_app.logger.error(f'Error generating reset token: {str(e)}', exc_info=True)
            flash('An error occurred while processing your request.', 'danger')
    
    return render_template('auth/request_reset.html', form=form)

@bp.route('/reset-password/<token>', methods=['GET', 'POST'])
@limiter.limit("3 per hour")
def reset_password(token):
    if current_user.is_authenticated:
        return redirect(url_for('main.calculator'))
    
    form = ResetPasswordForm()
    if form.validate_on_submit():
        try:
            user = User.query.filter_by(reset_token=token).first()
            if not user or not user.verify_reset_token(token):
                flash('The password reset link is invalid or has expired.', 'danger')
                return redirect(url_for('auth.request_reset'))
            
            user.set_password(form.password.data)
            db.session.commit()
            current_app.logger.info(f'Password reset successful for user {user.email}')
            flash('Your password has been reset. You can now log in.', 'success')
            return redirect(url_for('auth.login'))
            
        except Exception as e:
            current_app.logger.error(f'Error resetting password: {str(e)}', exc_info=True)
            flash('An error occurred while resetting your password.', 'danger')
    
    return render_template('auth/reset_password.html', form=form) 