"""
Shared Dependencies

Provides dependency injection for FastAPI routes.
All authentication, database access, and common dependencies are defined here.
"""

import sys
from pathlib import Path
from typing import Dict, Optional, List
from datetime import datetime

from fastapi import Depends, HTTPException, Query, Request, WebSocket
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials

# Add parent directory to path
sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent))

from modules.universal_logger import get_logger

logger = get_logger('API')

# Security
security = HTTPBearer(auto_error=False)


# ============================================================================
# GLOBAL STATE (imported from main app)
# ============================================================================

class AppState:
    """Global application state - singleton pattern"""
    _instance = None

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
            cls._instance._initialized = False
        return cls._instance

    def __init__(self):
        if self._initialized:
            return
        self.db = None
        self.config: Dict = {}
        self.scheduler = None
        self.websocket_manager = None  # ConnectionManager instance for broadcasts
        self.scraper_event_emitter = None  # ScraperEventEmitter for real-time scraping monitor
        self.active_scraper_sessions: Dict = {}  # Track active scraping sessions for monitor page
        self.running_platform_downloads: Dict = {}  # Track running platform downloads {platform: process}
        self.download_tasks: Dict = {}
        self.auth = None
        self.settings = None
        self.face_recognition_semaphore = None
        self.indexing_running: bool = False
        self.indexing_start_time = None
        self.review_rescan_running: bool = False
        self.review_rescan_progress: Dict = {"current": 0, "total": 0, "current_file": ""}
        self._initialized = True


def get_app_state() -> AppState:
    """Get the global application state"""
    return AppState()


# ============================================================================
# AUTHENTICATION DEPENDENCIES
# ============================================================================

async def get_current_user(
    request: Request,
    credentials: Optional[HTTPAuthorizationCredentials] = Depends(security)
) -> Dict:
    """
    Dependency to get current authenticated user from JWT token.
    Supports both Authorization header and cookie-based authentication.
    """
    app_state = get_app_state()
    auth_token = None

    # Try Authorization header first
    if credentials:
        auth_token = credentials.credentials
    # Try cookie second
    elif 'auth_token' in request.cookies:
        auth_token = request.cookies.get('auth_token')

    if not auth_token:
        raise HTTPException(status_code=401, detail="Not authenticated")

    if not app_state.auth:
        raise HTTPException(status_code=500, detail="Authentication not initialized")

    payload = app_state.auth.verify_session(auth_token)

    if not payload:
        raise HTTPException(status_code=401, detail="Invalid or expired token")

    return payload


async def get_current_user_optional(
    request: Request,
    credentials: Optional[HTTPAuthorizationCredentials] = Depends(security)
) -> Optional[Dict]:
    """Optional authentication dependency - returns None if not authenticated"""
    try:
        return await get_current_user(request, credentials)
    except HTTPException:
        return None


async def get_current_user_media(
    request: Request,
    credentials: Optional[HTTPAuthorizationCredentials] = Depends(security),
    token: Optional[str] = Query(None)
) -> Dict:
    """
    Authentication for media endpoints.
    Supports header, cookie, and query parameter tokens (for img/video tags).
    Priority: 1) Authorization header, 2) Cookie, 3) Query parameter
    """
    app_state = get_app_state()
    auth_token = None

    # Try to get token from Authorization header first (preferred)
    if credentials:
        auth_token = credentials.credentials
    # Try cookie second (for <img> and <video> tags)
    elif 'auth_token' in request.cookies:
        auth_token = request.cookies.get('auth_token')
    # Fall back to query parameter (for backward compatibility)
    elif token:
        auth_token = token

    if not auth_token:
        raise HTTPException(status_code=401, detail="Not authenticated")

    if not app_state.auth:
        raise HTTPException(status_code=500, detail="Authentication not initialized")

    payload = app_state.auth.verify_session(auth_token)
    if not payload:
        raise HTTPException(status_code=401, detail="Invalid or expired token")

    return payload


async def require_admin(
    request: Request,
    current_user: Dict = Depends(get_current_user)
) -> Dict:
    """Dependency to require admin role for sensitive operations"""
    app_state = get_app_state()
    username = current_user.get('sub')

    if not username:
        raise HTTPException(status_code=401, detail="Invalid user session")

    # Get user info to check role
    user_info = app_state.auth.get_user(username)
    if not user_info:
        raise HTTPException(status_code=401, detail="User not found")

    if user_info.get('role') != 'admin':
        logger.warning(f"User {username} attempted admin operation without admin role", module="Auth")
        raise HTTPException(status_code=403, detail="Admin role required")

    return current_user


# ============================================================================
# DATABASE DEPENDENCIES
# ============================================================================

def get_database():
    """Get the database connection"""
    app_state = get_app_state()
    if not app_state.db:
        raise HTTPException(status_code=500, detail="Database not initialized")
    return app_state.db


def get_settings_manager():
    """Get the settings manager"""
    app_state = get_app_state()
    if not app_state.settings:
        raise HTTPException(status_code=500, detail="Settings manager not initialized")
    return app_state.settings


# ============================================================================
# UTILITY DEPENDENCIES
# ============================================================================

def get_scheduler():
    """Get the scheduler instance"""
    app_state = get_app_state()
    return app_state.scheduler


def get_face_semaphore():
    """Get the face recognition semaphore for limiting concurrent operations"""
    app_state = get_app_state()
    return app_state.face_recognition_semaphore
