"""
Authentication API Routes
Login, Register, Logout, User Management
"""

from flask import Blueprint, request, jsonify, session
from flask_login import login_user, logout_user, login_required, current_user
from app import db, limiter
from app.models.user import User
from datetime import datetime, timedelta
import uuid
import jwt
import os

auth_api = Blueprint('auth_api', __name__)

SECRET_KEY = os.getenv('APP_SECRET_KEY', 'dev-secret')


# ============================================
# Public Routes
# ============================================

@auth_api.route('/health', methods=['GET'])
def health():
    """Health check endpoint"""
    return jsonify({'status': 'healthy', 'service': 'auth'})


@auth_api.route('/register', methods=['POST'])
@limiter.limit("5 per minute")
def register():
    """Register a new user"""
    data = request.get_json()
    
    # Validate required fields
    required_fields = ['username', 'email', 'password']
    for field in required_fields:
        if not data.get(field):
            return jsonify({'error': f'{field} is required'}), 400
    
    # Check if user exists
    if User.query.filter_by(username=data['username']).first():
        return jsonify({'error': 'Username already exists'}), 409
    
    if User.query.filter_by(email=data['email']).first():
        return jsonify({'error': 'Email already registered'}), 409
    
    # Validate password length
    if len(data['password']) < 6:
        return jsonify({'error': 'Password must be at least 6 characters'}), 400
    
    # Create new user
    user = User(
        username=data['username'],
        email=data['email'],
        first_name=data.get('first_name', ''),
        last_name=data.get('last_name', ''),
        company=data.get('company', ''),
        role=data.get('role', 'analyst'),
        gdpr_consent=data.get('gdpr_consent', False),
        research_only_acknowledged=data.get('research_only_acknowledged', False)
    )
    user.set_password(data['password'])
    
    # Set admin role for specific email (optional)
    if data['email'] == 'admin@wfis.io':
        user.is_admin = True
    
    db.session.add(user)
    db.session.commit()
    
    # Auto-login after registration
    login_user(user)
    
    return jsonify({
        'message': 'User registered successfully',
        'user': user.to_dict()
    }), 201


@auth_api.route('/login', methods=['POST'])
@limiter.limit("10 per minute")
def login():
    """Login user"""
    data = request.get_json()
    
    if not data.get('email') or not data.get('password'):
        return jsonify({'error': 'Email and password required'}), 400
    
    # Find user by email
    user = User.query.filter_by(email=data['email']).first()
    
    if not user or not user.check_password(data['password']):
        return jsonify({'error': 'Invalid email or password'}), 401
    
    if not user.is_active:
        return jsonify({'error': 'Account is disabled. Contact support.'}), 403
    
    # Update last login
    user.last_login = datetime.utcnow()
    db.session.commit()
    
    # Login user
    login_user(user, remember=data.get('remember', False))
    
    # Generate JWT token for API access
    token = jwt.encode({
        'user_id': user.id,
        'email': user.email,
        'role': user.role,
        'exp': datetime.utcnow() + timedelta(days=7)
    }, SECRET_KEY, algorithm='HS256')
    
    return jsonify({
        'message': 'Login successful',
        'user': user.to_dict(),
        'token': token,
        'is_admin': user.is_admin
    }), 200


@auth_api.route('/logout', methods=['POST'])
@login_required
def logout():
    """Logout user"""
    logout_user()
    session.clear()
    return jsonify({'message': 'Logout successful'}), 200


# ============================================
# User Management (Authenticated)
# ============================================

@auth_api.route('/profile', methods=['GET'])
@login_required
def get_profile():
    """Get current user profile"""
    return jsonify({'user': current_user.to_dict()}), 200


@auth_api.route('/profile', methods=['PUT'])
@login_required
def update_profile():
    """Update user profile"""
    data = request.get_json()
    
    # Update allowed fields
    allowed_fields = ['first_name', 'last_name', 'company', 'default_ticker', 'theme', 'email_notifications']
    for field in allowed_fields:
        if field in data:
            setattr(current_user, field, data[field])
    
    db.session.commit()
    return jsonify({'message': 'Profile updated', 'user': current_user.to_dict()}), 200


@auth_api.route('/change-password', methods=['POST'])
@login_required
def change_password():
    """Change user password"""
    data = request.get_json()
    
    if not current_user.check_password(data.get('current_password')):
        return jsonify({'error': 'Current password is incorrect'}), 401
    
    if len(data.get('new_password', '')) < 6:
        return jsonify({'error': 'New password must be at least 6 characters'}), 400
    
    current_user.set_password(data['new_password'])
    db.session.commit()
    
    return jsonify({'message': 'Password changed successfully'}), 200


# ============================================
# API Key Management
# ============================================

@auth_api.route('/api-keys', methods=['GET'])
@login_required
def get_api_keys():
    """Get all API keys for current user"""
    keys = APIKey.query.filter_by(user_id=current_user.id, is_active=True).all()
    return jsonify({
        'api_keys': [{
            'key': k.key,
            'name': k.name,
            'created_at': k.created_at.isoformat(),
            'last_used': k.last_used.isoformat() if k.last_used else None,
            'expires_at': k.expires_at.isoformat() if k.expires_at else None
        } for k in keys]
    }), 200


@auth_api.route('/api-keys', methods=['POST'])
@login_required
def create_api_key():
    """Create a new API key"""
    data = request.get_json()
    name = data.get('name', f'API Key {datetime.now().strftime("%Y-%m-%d")}')
    
    # Expiry (default 1 year)
    expires_days = data.get('expires_days', 365)
    expires_at = datetime.utcnow() + timedelta(days=expires_days)
    
    api_key = APIKey(
        user_id=current_user.id,
        name=name,
        expires_at=expires_at,
        is_active=True
    )
    
    db.session.add(api_key)
    db.session.commit()
    
    return jsonify({
        'message': 'API key created',
        'api_key': api_key.key,
        'name': api_key.name,
        'expires_at': api_key.expires_at.isoformat()
    }), 201


@auth_api.route('/api-keys/<key>', methods=['DELETE'])
@login_required
def revoke_api_key(key):
    """Revoke an API key"""
    api_key = APIKey.query.filter_by(key=key, user_id=current_user.id).first()
    
    if not api_key:
        return jsonify({'error': 'API key not found'}), 404
    
    api_key.is_active = False
    db.session.commit()
    
    return jsonify({'message': 'API key revoked'}), 200


# ============================================
# Admin Routes
# ============================================

@auth_api.route('/admin/users', methods=['GET'])
@login_required
def admin_get_users():
    """Admin: Get all users"""
    if not current_user.is_admin:
        return jsonify({'error': 'Admin access required'}), 403
    
    users = User.query.all()
    return jsonify({
        'users': [u.to_dict() for u in users],
        'total': len(users)
    }), 200


@auth_api.route('/admin/users/<int:user_id>', methods=['GET'])
@login_required
def admin_get_user(user_id):
    """Admin: Get specific user details"""
    if not current_user.is_admin:
        return jsonify({'error': 'Admin access required'}), 403
    
    user = User.query.get_or_404(user_id)
    
    # Get user statistics
    analyses_count = len(user.analyses)
    watchlists_count = len(user.watchlists)
    api_keys_count = len([k for k in user.api_keys if k.is_active])
    
    return jsonify({
        'user': user.to_dict(),
        'statistics': {
            'analyses_count': analyses_count,
            'watchlists_count': watchlists_count,
            'api_keys_count': api_keys_count
        }
    }), 200


@auth_api.route('/admin/users/<int:user_id>/toggle-status', methods=['POST'])
@login_required
def admin_toggle_user_status(user_id):
    """Admin: Enable/Disable user account"""
    if not current_user.is_admin:
        return jsonify({'error': 'Admin access required'}), 403
    
    user = User.query.get_or_404(user_id)
    
    # Prevent admin from disabling themselves
    if user.id == current_user.id:
        return jsonify({'error': 'You cannot disable your own account'}), 400
    
    user.is_active = not user.is_active
    db.session.commit()
    
    return jsonify({
        'message': f'User {user.username} {"enabled" if user.is_active else "disabled"}',
        'is_active': user.is_active
    }), 200


@auth_api.route('/admin/users/<int:user_id>/role', methods=['PUT'])
@login_required
def admin_update_user_role(user_id):
    """Admin: Update user role"""
    if not current_user.is_admin:
        return jsonify({'error': 'Admin access required'}), 403
    
    user = User.query.get_or_404(user_id)
    data = request.get_json()
    
    valid_roles = ['analyst', 'admin', 'enterprise']
    new_role = data.get('role')
    
    if new_role not in valid_roles:
        return jsonify({'error': f'Invalid role. Must be one of: {valid_roles}'}), 400
    
    # Prevent removing admin role from last admin
    if user.is_admin and new_role != 'admin' and User.query.filter_by(is_admin=True).count() <= 1:
        return jsonify({'error': 'Cannot remove admin role from the last admin user'}), 400
    
    user.role = new_role
    user.is_admin = (new_role == 'admin')
    db.session.commit()
    
    return jsonify({
        'message': f'User {user.username} role updated to {new_role}',
        'role': user.role,
        'is_admin': user.is_admin
    }), 200


@auth_api.route('/admin/stats', methods=['GET'])
@login_required
def admin_get_stats():
    """Admin: Get platform statistics"""
    if not current_user.is_admin:
        return jsonify({'error': 'Admin access required'}), 403
    
    total_users = User.query.count()
    active_users = User.query.filter_by(is_active=True).count()
    admin_count = User.query.filter_by(is_admin=True).count()
    
    # Recent registrations (last 7 days)
    week_ago = datetime.utcnow() - timedelta(days=7)
    new_users_week = User.query.filter(User.created_at >= week_ago).count()
    
    return jsonify({
        'users': {
            'total': total_users,
            'active': active_users,
            'admins': admin_count,
            'new_last_7_days': new_users_week
        },
        'timestamp': datetime.utcnow().isoformat()
    }), 200


# ============================================
# Token Verification (for API middleware)
# ============================================

def verify_token(token):
    """Verify JWT token and return user"""
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=['HS256'])
        user = User.query.get(payload['user_id'])
        if user and user.is_active:
            return user
        return None
    except (jwt.InvalidTokenError, jwt.ExpiredSignatureError):
        return None