"""
Authentication Routes Blueprint
Contains login, registration, password reset functionality
"""
from flask import Blueprint, request, render_template, redirect, url_for, flash, jsonify, session
from sqlalchemy import create_engine, text
from sqlalchemy.orm import sessionmaker
import secrets
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import os

# Use passlib for password verification to match the hashing method
from passlib.context import CryptContext

# Password hashing context - should match what's used in registration
# Using a more compatible configuration for bcrypt
try:
    pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
except Exception:
    # Fallback configuration if there are issues with bcrypt
    pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto", 
                              bcrypt__backends=["bcrypt", "os_crypt"])

def verify_password(password: str, password_hash: str) -> bool:
    """
    Verify password against hash with error handling for bcrypt compatibility issues
    """
    try:
        return pwd_context.verify(password, password_hash)
    except AttributeError as e:
        # Handle the bcrypt.__about__ issue
        if "__about__" in str(e):
            # Fallback: try direct bcrypt import and verification
            try:
                import bcrypt
                # Convert password to bytes
                password_bytes = password.encode('utf-8')
                # Convert hash to bytes if it's not already
                if isinstance(password_hash, str):
                    hash_bytes = password_hash.encode('utf-8')
                else:
                    hash_bytes = password_hash
                return bcrypt.checkpw(password_bytes, hash_bytes)
            except Exception:
                # If all else fails, fall back to False (failed verification)
                return False
        else:
            # Re-raise if it's a different AttributeError
            raise
    except Exception:
        # Any other exception during verification
        return False

# Create Blueprint
auth_bp = Blueprint('auth', __name__)

@auth_bp.route('/register')
def register():
    """User registration page"""
    from config import ADMIN_CONFIG
    return render_template('register.html', google_maps_key=ADMIN_CONFIG.get('GOOGLE_MAPS_API_KEY', 'your-google-maps-api-key'))

@auth_bp.route('/login', methods=['GET', 'POST'])
def login():
    """User login page and authentication"""
    if request.method == 'POST':
        from config import ADMIN_CONFIG
        
        # Safely get form data
        email = request.form.get('email', '').strip()
        password = request.form.get('password', '').strip()
        
        # Validate required fields
        if not email or not password:
            flash('Email and password are required.', 'error')
            return render_template('login.html')
        
        # Check if this is an admin login
        # Admins can log in with either email or username
        DATABASE_URL = ADMIN_CONFIG['DATABASE_URL']
        engine = create_engine(DATABASE_URL)
        SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
        
        db = SessionLocal()
        
        try:
            # First check if this is a database admin user
            user_result = db.execute(text("""
                SELECT u.user_id, u.password_hash, u.first_name, u.last_name, u.email, u.is_email_verified, u.profile_photo_path,
                       ur.role_name
                FROM users u
                LEFT JOIN user_roles ur ON u.role_id = ur.role_id
                WHERE (u.email = :email OR u.first_name = :email)
                AND u.is_active = true
            """), {'email': email}).fetchone()
            
            if user_result and user_result.password_hash:
                # Use our custom verify method to handle bcrypt compatibility issues
                if verify_password(password, user_result.password_hash):
                    # Check if this is an admin user
                    is_admin = False
                    if user_result.role_name and user_result.role_name.lower() == 'admin':
                        is_admin = True
                    
                    if not user_result.is_email_verified and not is_admin:
                        flash('Please verify your email address before logging in.', 'warning')
                        return render_template('login.html')
                    
                    # Set session
                    session['user_id'] = str(user_result.user_id)
                    session['user_email'] = user_result.email
                    session['user_name'] = f"{user_result.first_name} {user_result.last_name}"
                    # Store user photo in session if available
                    if user_result.profile_photo_path:
                        session['user_photo'] = user_result.profile_photo_path
                    
                    # Set admin flag in session
                    session['is_admin'] = is_admin
                    
                    flash('Login successful!', 'success')
                    
                    # If this is an admin user, redirect to admin dashboard
                    if is_admin:
                        return redirect(url_for('admin.admin_dashboard'))
                    
                    # Redirect to next page if specified, otherwise to home
                    next_page = request.args.get('next')
                    return redirect(next_page) if next_page else redirect(url_for('main.index'))
                else:
                    flash('Invalid email or password.', 'error')
            else:
                # Check hardcoded admin credentials as fallback
                if email == ADMIN_CONFIG['ADMIN_USERNAME'] and password == ADMIN_CONFIG['ADMIN_PASSWORD']:
                    session['admin_logged_in'] = True
                    session['admin_username'] = email
                    session['user_id'] = 'admin'
                    session['is_admin'] = True
                    flash('Admin login successful!', 'success')
                    return redirect(url_for('admin.admin_dashboard'))
                else:
                    flash('Invalid email or password.', 'error')
                
        except Exception as e:
            flash(f'An error occurred during login: {str(e)}', 'error')
        finally:
            db.close()
    
    return render_template('login.html')

@auth_bp.route('/forgot-password', methods=['GET'])
def forgot_password():
    """Forgot password page"""
    return render_template('forgot-password.html')

@auth_bp.route('/logout')
def logout():
    """User logout"""
    session.clear()
    flash('You have been logged out.', 'info')
    return redirect(url_for('main.index'))

@auth_bp.route('/api/send-verification', methods=['POST'])
def send_verification():
    """Send email verification"""
    try:
        from config import ADMIN_CONFIG, send_email
        
        data = request.get_json()
        email = data.get('email')
        
        if not email:
            return jsonify({'success': False, 'message': 'Email is required'}), 400
        
        # Database connection
        DATABASE_URL = ADMIN_CONFIG['DATABASE_URL']
        engine = create_engine(DATABASE_URL)
        SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
        
        db = SessionLocal()
        
        try:
            # Check if user exists
            user_result = db.execute(text("""
                SELECT user_id, first_name, email, is_email_verified
                FROM users 
                WHERE email = :email
            """), {'email': email}).fetchone()
            
            if not user_result:
                return jsonify({'success': False, 'message': 'Email not found'}), 404
            
            if user_result.is_email_verified:
                return jsonify({'success': False, 'message': 'Email is already verified'}), 400
            
            # Generate verification token
            verification_token = secrets.token_urlsafe(32)
            
            # Store verification token
            db.execute(text("""
                UPDATE users 
                SET verification_token = :token, verification_token_expires = NOW() + INTERVAL '24 hours'
                WHERE email = :email
            """), {'token': verification_token, 'email': email})
            db.commit()
            
            # Send verification email
            verification_url = f"{request.host_url}api/verify-email?token={verification_token}"
            
            subject = "Verify Your Email Address"
            body = f"""
            Hello {user_result.first_name},
            
            Please click the link below to verify your email address:
            {verification_url}
            
            This link will expire in 24 hours.
            
            If you didn't create an account, please ignore this email.
            
            Best regards,
            The BookBeach Team
            """
            
            success = send_email(email, subject, body)
            
            if success:
                return jsonify({'success': True, 'message': 'Verification email sent successfully'})
            else:
                return jsonify({'success': False, 'message': 'Failed to send verification email'}), 500
                
        except Exception as e:
            db.rollback()
            return jsonify({'success': False, 'message': f'Database error: {str(e)}'}), 500
        finally:
            db.close()
            
    except Exception as e:
        return jsonify({'success': False, 'message': f'Server error: {str(e)}'}), 500

@auth_bp.route('/api/verify-email', methods=['POST'])
def verify_email():
    """Verify email address"""
    try:
        from config import ADMIN_CONFIG
        
        data = request.get_json()
        token = data.get('token')
        
        if not token:
            return jsonify({'success': False, 'message': 'Verification token is required'}), 400
        
        # Database connection
        DATABASE_URL = ADMIN_CONFIG['DATABASE_URL']
        engine = create_engine(DATABASE_URL)
        SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
        
        db = SessionLocal()
        
        try:
            # Check if token exists and is valid
            user_result = db.execute(text("""
                SELECT user_id, email, first_name
                FROM users 
                WHERE verification_token = :token 
                AND verification_token_expires > NOW()
                AND is_email_verified = false
            """), {'token': token}).fetchone()
            
            if not user_result:
                return jsonify({'success': False, 'message': 'Invalid or expired verification token'}), 400
            
            # Mark user as verified
            db.execute(text("""
                UPDATE users 
                SET is_email_verified = true, verification_token = NULL, verification_token_expires = NULL
                WHERE user_id = :user_id
            """), {'user_id': user_result.user_id})
            db.commit()
            
            return jsonify({
                'success': True, 
                'message': 'Email verified successfully',
                'user': {
                    'email': user_result.email,
                    'first_name': user_result.first_name
                }
            })
            
        except Exception as e:
            db.rollback()
            return jsonify({'success': False, 'message': f'Database error: {str(e)}'}), 500
        finally:
            db.close()
            
    except Exception as e:
        return jsonify({'success': False, 'message': f'Server error: {str(e)}'}), 500

# More auth routes will be added here...