"""
JWT Authentication Manager for SkillDarbar API
"""
try:
    import jwt
except ImportError:
    print("PyJWT not installed. Run: pip install PyJWT")
    raise

import os
import logging
from datetime import datetime, timedelta
from functools import wraps
from flask import request, jsonify, g

logger = logging.getLogger(__name__)

def _get_jwt_secret_key():
    """Get JWT secret key from config or environment"""
    try:
        from config.config_settings import APP_CONFIG
        return APP_CONFIG.get('jwt_secret_key', os.getenv('JWT_SECRET_KEY', 'your-super-secret-jwt-key-change-in-production'))
    except ImportError:
        return os.getenv('JWT_SECRET_KEY', 'your-super-secret-jwt-key-change-in-production')

class JWTManager:
    SECRET_KEY = _get_jwt_secret_key()
    ALGORITHM = 'HS256'
    ACCESS_TOKEN_EXPIRE_HOURS = 24
    REFRESH_TOKEN_EXPIRE_DAYS = 30
    
    @classmethod
    def generate_tokens(cls, user_id: str, user_email: str):
        """Generate access and refresh tokens"""
        now = datetime.utcnow()
        
        # Access token payload
        access_payload = {
            'user_id': str(user_id),
            'email': user_email,
            'type': 'access',
            'exp': now + timedelta(hours=cls.ACCESS_TOKEN_EXPIRE_HOURS),
            'iat': now
        }
        
        # Refresh token payload
        refresh_payload = {
            'user_id': str(user_id),
            'type': 'refresh',
            'exp': now + timedelta(days=cls.REFRESH_TOKEN_EXPIRE_DAYS),
            'iat': now
        }
        
        access_token = jwt.encode(access_payload, cls.SECRET_KEY, algorithm=cls.ALGORITHM)
        refresh_token = jwt.encode(refresh_payload, cls.SECRET_KEY, algorithm=cls.ALGORITHM)
        
        # Ensure tokens are strings (handle both PyJWT versions)
        if isinstance(access_token, bytes):
            access_token = access_token.decode('utf-8')
        if isinstance(refresh_token, bytes):
            refresh_token = refresh_token.decode('utf-8')
        
        return access_token, refresh_token
    
    @classmethod
    def verify_token(cls, token: str, token_type: str = 'access'):
        """Verify and decode JWT token"""
        try:
            payload = jwt.decode(token, cls.SECRET_KEY, algorithms=[cls.ALGORITHM])
            
            if payload.get('type') != token_type:
                raise jwt.InvalidTokenError('Invalid token type')
                
            return payload
        except jwt.ExpiredSignatureError:
            raise jwt.InvalidTokenError('Token has expired')
        except jwt.InvalidTokenError:
            raise jwt.InvalidTokenError('Invalid token')
        except Exception as e:
            logger.error(f"Token verification error: {str(e)}")
            raise jwt.InvalidTokenError('Token verification failed')

def require_auth(f):
    """Decorator to require JWT authentication"""
    @wraps(f)
    def decorated_function(*args, **kwargs):
        auth_header = request.headers.get('Authorization')
        if not auth_header:
            logger.warning(f"require_auth: No Authorization header for {request.path}")
            return jsonify({'response': 'failure', 'error': 'Authorization header required'}), 401
            
        if not auth_header.startswith('Bearer '):
            logger.warning(f"require_auth: Invalid format for {request.path}")
            return jsonify({'response': 'failure', 'error': 'Invalid authorization format'}), 401
            
        token = auth_header.split(' ')[1]
        try:
            payload = JWTManager.verify_token(token)
            g.current_user_id = payload['user_id']
            g.current_user_email = payload['email']
        except jwt.InvalidTokenError as e:
            return jsonify({'response': 'failure', 'error': str(e)}), 401
        
        return f(*args, **kwargs)
    return decorated_function

def require_user_access(f):
    """Decorator to ensure user can only access their own data"""
    @wraps(f)
    def decorated_function(*args, **kwargs):
        if hasattr(g, 'current_user_id') and g.current_user_id:
            pass  # User is authenticated
        else:
            user_id = None
            if request.method == 'GET':
                user_id = request.args.get('user_id')
            elif request.method == 'POST':
                user_id = (request.form.get('user_id') or 
                          (request.json.get('user_id') if request.is_json else None))
            
            if not user_id:
                return f(*args, **kwargs)
            
            if hasattr(g, 'current_user_id') and str(g.current_user_id) != str(user_id):
                return jsonify({'response': 'failure', 'error': 'Access denied'}), 403
        
        return f(*args, **kwargs)
    return decorated_function

def optional_auth(f):
    """Decorator for endpoints that can work with or without authentication"""
    @wraps(f)
    def decorated_function(*args, **kwargs):
        auth_header = request.headers.get('Authorization')
        if auth_header and auth_header.startswith('Bearer '):
            token = auth_header.split(' ')[1]
            try:
                payload = JWTManager.verify_token(token)
                g.current_user_id, g.current_user_email = payload['user_id'], payload['email']
            except jwt.InvalidTokenError:
                g.current_user_id, g.current_user_email = None, None
        else:
            g.current_user_id, g.current_user_email = None, None
        
        return f(*args, **kwargs)
    return decorated_function
