"""
AI Model Preference API Routes
Handles global user AI model selection and access management
"""

from flask import Blueprint, request, jsonify, g
from database import get_db_connection
from utils.decorators import require_api_key
from auth.jwt_manager import optional_auth
from utils.response_helpers import create_success_response, create_error_response
from services.subscription_manager import SubscriptionManager
import logging
import json

logger = logging.getLogger(__name__)

model_preference_bp = Blueprint('model_preference', __name__)


def check_user_model_access(user_id: int, model_name: str) -> dict:
    """
    Check if user has access to a specific AI model
    
    Returns:
        {
            'has_access': bool,
            'reason': str,  # 'free_model', 'package_grant', 'subscription', 'requires_purchase'
            'expires_at': datetime or None,
            'upgrade_options': list  # If no access, suggests packages
        }
    """
    conn = None
    try:
        conn = get_db_connection()
        cursor = conn.cursor(dictionary=True)
        
        # Check 1: Free models (always accessible)
        cursor.execute("""
            SELECT name, tier FROM ai_models 
            WHERE name = %s AND status IN ('active', 'working')
        """, (model_name,))
        
        model = cursor.fetchone()
        if not model:
            return {
                'has_access': False,
                'reason': 'model_not_found',
                'message': f'Model {model_name} not found or inactive'
            }
        
        if model.get('tier') == 'free':
            return {
                'has_access': True,
                'reason': 'free_model',
                'expires_at': None
            }
        
        # Check 2: User-specific model access grants (from packages)
        cursor.execute("""
            SELECT access_type, expires_at, granted_by_package_id
            FROM user_model_access
            WHERE user_id = %s 
            AND model_name = %s 
            AND is_active = TRUE
            AND (expires_at IS NULL OR expires_at > NOW())
            LIMIT 1
        """, (user_id, model_name))
        
        access_grant = cursor.fetchone()
        if access_grant:
            return {
                'has_access': True,
                'reason': access_grant['access_type'],
                'expires_at': access_grant['expires_at'].isoformat() if access_grant['expires_at'] else None,
                'package_id': access_grant['granted_by_package_id']
            }
        
        # Check 3: Subscription includes model
        # TODO: Implement subscription-based model access if needed
        # For now, skipping subscription check
        
        # No access - get packages that grant this model
        cursor.execute("""
            SELECT id, package_name, price_npr, price_usd, grants_models
            FROM ai_token_packages
            WHERE is_active = TRUE
            AND JSON_CONTAINS(grants_models, JSON_QUOTE(%s))
            ORDER BY price_usd ASC
            LIMIT 3
        """, (model_name,))
        
        upgrade_options = cursor.fetchall()
        
        return {
            'has_access': False,
            'reason': 'requires_purchase',
            'message': f'Model {model_name} requires a premium package',
            'upgrade_options': upgrade_options
        }
        
    except Exception as e:
        logger.error(f"Error checking model access: {e}")
        return {
            'has_access': False,
            'reason': 'error',
            'message': str(e)
        }
    finally:
        if conn:
            conn.close()


@model_preference_bp.route('/api/models/preference', methods=['GET'])
@require_api_key
@optional_auth
def get_model_preference():
    """Get user's global AI model preference"""
    user_id = g.current_user_id
    
    conn = None
    try:
        conn = get_db_connection()
        cursor = conn.cursor(dictionary=True)
        
        # Get user's preferred model
        cursor.execute("""
            SELECT preferred_ai_model, model_selection_synced_at
            FROM user
            WHERE id = %s
        """, (user_id,))
        
        user = cursor.fetchone()
        
        if not user:
            return create_error_response('User not found', status_code=404)
        
        preferred_model = user['preferred_ai_model'] or 'llama-3.3-70b'
        
        return create_success_response(
            data={
                'preferred_model': preferred_model,
                'synced_at': user['model_selection_synced_at'].isoformat() if user['model_selection_synced_at'] else None
            },
            message='Model preference retrieved successfully'
        )
        
    except Exception as e:
        logger.error(f"Error getting model preference: {e}")
        return create_error_response(str(e), status_code=500)
    finally:
        if conn:
            conn.close()


@model_preference_bp.route('/api/models/preference', methods=['POST'])
@require_api_key
@optional_auth
def set_model_preference():
    """Set user's global AI model preference"""
    user_id = g.current_user_id
    data = request.get_json()
    
    if not data:
        return create_error_response('No data provided', status_code=400)
    
    model_name = data.get('model_name')
    
    if not model_name:
        return create_error_response('model_name is required', status_code=400)
    
    conn = None
    try:
        conn = get_db_connection()
        cursor = conn.cursor(dictionary=True)
        
        # Validate model exists
        cursor.execute("""
            SELECT name, tier FROM ai_models
            WHERE name = %s AND status IN ('active', 'working')
        """, (model_name,))
        
        model = cursor.fetchone()
        if not model:
            logger.warning(f"Model {model_name} not found in ai_models table")
            return create_error_response(
                f'Model {model_name} not found or inactive',
                status_code=404
            )
        
        # For free tier models, allow access directly
        # For paid models, would need to check access (simplified for now)
        is_free = model.get('tier') == 'free'
        
        if not is_free:
            # Check if user has access to premium model
            access_check = check_user_model_access(user_id, model_name)
            if not access_check['has_access']:
                return create_error_response(
                    access_check.get('message', 'Access denied for this model'),
                    status_code=403
                )
        
        # Update user's preference
        cursor.execute("""
            UPDATE user
            SET preferred_ai_model = %s,
                model_selection_synced_at = NOW()
            WHERE id = %s
        """, (model_name, user_id))
        
        conn.commit()
        
        logger.info(f"User {user_id} set preferred model to {model_name}")
        
        return create_success_response(
            data={
                'preferred_model': model_name,
                'access_type': 'free_model' if is_free else 'granted'
            },
            message=f'Successfully set default model to {model_name}'
        )
        
    except Exception as e:
        if conn:
            conn.rollback()
        logger.error(f"Error setting model preference: {e}")
        return create_error_response(str(e), status_code=500)
    finally:
        if conn:
            conn.close()


@model_preference_bp.route('/api/models/check-access', methods=['POST'])
@require_api_key
@optional_auth
def check_model_access():
    """Check if user has access to a specific model"""
    user_id = g.current_user_id
    data = request.get_json()
    
    if not data:
        return create_error_response('No data provided', status_code=400)
    
    model_name = data.get('model_name')
    
    if not model_name:
        return create_error_response('model_name is required', status_code=400)
    
    result = check_user_model_access(user_id, model_name)
    
    return create_success_response(
        data=result,
        message='Access check completed'
    )
