from flask import Blueprint, request, jsonify, session, current_app, redirect, url_for
from authlib.integrations.flask_client import OAuth
from authlib.common.errors import AuthlibBaseError
import os
from src.models.user import db, User
from datetime import datetime
import secrets

auth_real_bp = Blueprint('auth_real', __name__)

# Initialize OAuth
oauth = OAuth()

def init_oauth(app):
    """Initialize OAuth with the Flask app"""
    oauth.init_app(app)
    
    # Register Google OAuth provider
    google = oauth.register(
        name='google',
        client_id=os.environ.get('GOOGLE_CLIENT_ID'),
        client_secret=os.environ.get('GOOGLE_CLIENT_SECRET'),
        server_metadata_url='https://accounts.google.com/.well-known/openid_connect_configuration',
        client_kwargs={
            'scope': 'openid email profile'
        }
    )
    return google

@auth_real_bp.route('/google-login', methods=['GET'])
def google_login():
    """Initiate Google OAuth login"""
    try:
        # Generate a random state parameter for security
        state = secrets.token_urlsafe(32)
        session['oauth_state'] = state
        
        # Get the Google OAuth client
        google = oauth.google
        
        # Create the authorization URL
        redirect_uri = url_for('auth_real.google_callback', _external=True)
        
        return google.authorize_redirect(redirect_uri, state=state)
        
    except Exception as e:
        current_app.logger.error(f"Google login initiation error: {str(e)}")
        return jsonify({'error': 'Failed to initiate Google login'}), 500

@auth_real_bp.route('/google-callback', methods=['GET'])
def google_callback():
    """Handle Google OAuth callback"""
    try:
        # Verify state parameter
        if request.args.get('state') != session.get('oauth_state'):
            return jsonify({'error': 'Invalid state parameter'}), 400
        
        # Clear the state from session
        session.pop('oauth_state', None)
        
        # Get the Google OAuth client
        google = oauth.google
        
        # Exchange authorization code for tokens
        token = google.authorize_access_token()
        
        # Get user info from Google
        user_info = token.get('userinfo')
        if not user_info:
            # Fallback: fetch user info manually
            resp = google.parse_id_token(token)
            user_info = resp
        
        # Check if user exists in our database
        user = User.query.filter_by(google_id=user_info['sub']).first()
        
        if not user:
            # Create new user
            user = User(
                google_id=user_info['sub'],
                email=user_info['email'],
                name=user_info['name'],
                picture=user_info.get('picture'),
                full_name=user_info['name'],
                job_title='Property Manager',
                created_at=datetime.utcnow()
            )
            db.session.add(user)
            db.session.commit()
            
            # This is a new user signup
            is_new_user = True
        else:
            # Existing user login
            is_new_user = False
            # Update user info from Google
            user.name = user_info['name']
            user.email = user_info['email']
            user.picture = user_info.get('picture')
            if not user.full_name:
                user.full_name = user_info['name']
            db.session.commit()
        
        # Store user ID in session
        session['user_id'] = user.id
        session['is_new_user'] = is_new_user
        
        # Redirect to frontend with success
        if is_new_user:
            return redirect('/?signup=success')
        else:
            return redirect('/?login=success')
        
    except AuthlibBaseError as e:
        current_app.logger.error(f"OAuth error: {str(e)}")
        return redirect('/?error=oauth_failed')
    except Exception as e:
        current_app.logger.error(f"Google callback error: {str(e)}")
        return redirect('/?error=login_failed')

@auth_real_bp.route('/logout', methods=['POST'])
def logout():
    """Logout user"""
    session.clear()
    return jsonify({'success': True})

@auth_real_bp.route('/me', methods=['GET'])
def get_current_user():
    """Get current authenticated user"""
    user_id = session.get('user_id')
    if not user_id:
        return jsonify({'error': 'Not authenticated'}), 401
    
    user = User.query.get(user_id)
    if not user:
        return jsonify({'error': 'User not found'}), 404
    
    return jsonify({
        'user': user.to_dict(),
        'is_new_user': session.get('is_new_user', False)
    })

@auth_real_bp.route('/profile', methods=['PUT'])
def update_profile():
    """Update user profile"""
    user_id = session.get('user_id')
    if not user_id:
        return jsonify({'error': 'Not authenticated'}), 401
    
    user = User.query.get(user_id)
    if not user:
        return jsonify({'error': 'User not found'}), 404
    
    data = request.get_json()
    
    # Update user profile fields
    if 'full_name' in data:
        user.full_name = data['full_name']
        user.name = data['full_name']  # Keep name in sync
    if 'job_title' in data:
        user.job_title = data['job_title']
    if 'phone_number' in data:
        user.phone_number = data['phone_number']
    if 'profile_picture' in data:
        user.profile_picture = data['profile_picture']
    if 'company_name' in data:
        user.company_name = data['company_name']
    if 'company_logo' in data:
        user.company_logo = data['company_logo']
    if 'license_number' in data:
        user.license_number = data['license_number']
    if 'company_address' in data:
        user.company_address = data['company_address']
    if 'company_phone' in data:
        user.company_phone = data['company_phone']
    if 'company_email' in data:
        user.company_email = data['company_email']
    if 'owner_name' in data:
        user.owner_name = data['owner_name']
    if 'owner_email' in data:
        user.owner_email = data['owner_email']
    if 'owner_phone' in data:
        user.owner_phone = data['owner_phone']
    
    try:
        db.session.commit()
        
        # Clear the new user flag after first profile update
        session.pop('is_new_user', None)
        
        return jsonify({
            'success': True,
            'user': user.to_dict()
        })
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f"Profile update error: {str(e)}")
        return jsonify({'error': str(e)}), 500

@auth_real_bp.route('/check-auth', methods=['GET'])
def check_auth():
    """Check if user is authenticated (for frontend polling)"""
    user_id = session.get('user_id')
    if user_id:
        user = User.query.get(user_id)
        if user:
            return jsonify({
                'authenticated': True,
                'user': user.to_dict(),
                'is_new_user': session.get('is_new_user', False)
            })
    
    return jsonify({'authenticated': False}), 401

