"""
API Router pentru managementul cache-ului
"""
from fastapi import APIRouter, Depends, HTTPException, Request
from pydantic import BaseModel
from typing import Optional, Dict, Any
# import sys  # Removed - no longer needed
import os
import time
from datetime import datetime, timedelta


from shared.auth.dependencies import get_current_user
from shared.auth.models import CurrentUser
from ..cache import get_cache, get_event_monitor, toggle_event_monitor

router = APIRouter(tags=["cache"])


# Pydantic Models

class CacheStatsResponse(BaseModel):
    """Răspuns statistici cache"""
    enabled: bool
    global_enabled: bool
    user_enabled: bool
    cache_type: str
    hit_rate: float
    total_hits: int
    total_misses: int
    queries_saved: Dict[str, int]
    response_times: Dict[str, Dict[str, Any]]
    cache_size: Dict[str, int]
    auto_invalidate: bool
    last_cleanup: Optional[str] = None


class InvalidateCacheRequest(BaseModel):
    """Request pentru invalidare cache"""
    company_id: Optional[int] = None
    cache_type: Optional[str] = None


class ToggleUserCacheRequest(BaseModel):
    """Request pentru toggle cache per-user"""
    enabled: bool


class ToggleGlobalCacheRequest(BaseModel):
    """Request pentru toggle cache global"""
    enabled: bool


class ToggleAutoInvalidateRequest(BaseModel):
    """Request pentru toggle auto-invalidation"""
    enabled: bool


# Helper Functions

async def _calculate_cache_stats() -> Dict[str, Any]:
    """Calculate comprehensive cache statistics"""
    cache = get_cache()
    if not cache:
        raise HTTPException(status_code=503, detail="Cache not initialized")

    # Get basic cache stats
    stats = await cache.get_stats()

    # Calculate hit rate
    memory_stats = stats.get('memory', {})
    total_hits = memory_stats.get('hits', 0)
    total_misses = memory_stats.get('misses', 0)
    total_requests = total_hits + total_misses
    hit_rate = (total_hits / total_requests * 100) if total_requests > 0 else 0

    # Calculate queries saved (from performance_log)
    queries_saved = await _calculate_queries_saved(cache)

    # Calculate response times per cache type
    response_times = await _calculate_response_times(cache)

    # Get cache sizes
    cache_size = {
        'memory': memory_stats.get('size', 0),
        'sqlite': stats.get('sqlite', {}).get('active_entries', 0)
    }

    # Get event monitor status
    monitor = get_event_monitor()
    auto_invalidate = monitor.running if monitor else False

    return {
        'enabled': cache.config.enabled,
        'global_enabled': cache.config.enabled,
        'cache_type': cache.config.cache_type,
        'hit_rate': round(hit_rate, 1),
        'total_hits': total_hits,
        'total_misses': total_misses,
        'queries_saved': queries_saved,
        'response_times': response_times,
        'cache_size': cache_size,
        'auto_invalidate': auto_invalidate,
        'last_cleanup': None  # TODO: track last cleanup time
    }


async def _calculate_queries_saved(cache) -> Dict[str, int]:
    """Calculate queries saved by time period"""
    import aiosqlite

    try:
        async with aiosqlite.connect(cache.sqlite.db_path) as db:
            now = time.time()
            today_start = now - 86400  # 24 hours
            week_start = now - 604800  # 7 days

            # Today
            async with db.execute("""
                SELECT COUNT(*) FROM performance_log
                WHERE cache_hit = 1 AND timestamp >= ?
            """, (today_start,)) as cursor:
                today = (await cursor.fetchone())[0]

            # This week
            async with db.execute("""
                SELECT COUNT(*) FROM performance_log
                WHERE cache_hit = 1 AND timestamp >= ?
            """, (week_start,)) as cursor:
                week = (await cursor.fetchone())[0]

            # All time
            async with db.execute("""
                SELECT COUNT(*) FROM performance_log
                WHERE cache_hit = 1
            """) as cursor:
                total = (await cursor.fetchone())[0]

            return {
                'today': today,
                'week': week,
                'total': total
            }
    except Exception as e:
        return {'today': 0, 'week': 0, 'total': 0}


async def _calculate_response_times(cache) -> Dict[str, Dict[str, Any]]:
    """Calculate average response times per cache type"""
    import aiosqlite

    try:
        async with aiosqlite.connect(cache.sqlite.db_path) as db:
            # Get average times per cache type
            async with db.execute("""
                SELECT
                    cache_type,
                    AVG(CASE WHEN cache_hit = 1 THEN response_time_ms ELSE NULL END) as avg_cached,
                    AVG(CASE WHEN cache_hit = 0 THEN response_time_ms ELSE NULL END) as avg_oracle
                FROM performance_log
                WHERE timestamp >= ?
                GROUP BY cache_type
            """, (time.time() - 86400,)) as cursor:  # Last 24 hours
                results = await cursor.fetchall()

            response_times = {}
            for row in results:
                cache_type, avg_cached, avg_oracle = row
                if avg_cached and avg_oracle:
                    improvement = int((avg_oracle - avg_cached) / avg_oracle * 100)
                    response_times[cache_type] = {
                        'cached': int(avg_cached),
                        'oracle': int(avg_oracle),
                        'improvement': improvement
                    }

            return response_times
    except Exception as e:
        return {}


# API Endpoints

@router.get("/stats", response_model=CacheStatsResponse)
async def get_cache_stats(
    current_user: CurrentUser = Depends(get_current_user)
):
    """
    Obține statistici complete cache

    Returns:
        - Hit rate, queries saved, response times
        - Cache sizes (memory + SQLite)
        - Auto-invalidation status
        - Per-user cache setting
    """
    try:
        cache = get_cache()
        if not cache:
            raise HTTPException(status_code=503, detail="Cache not initialized")

        # Get base stats
        stats = await _calculate_cache_stats()

        # Add user-specific setting
        user_enabled = await cache.is_enabled_for_user(current_user.username)
        stats['user_enabled'] = user_enabled

        return CacheStatsResponse(**stats)

    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Error retrieving cache stats: {str(e)}")


@router.post("/invalidate")
async def invalidate_cache(
    request: InvalidateCacheRequest,
    current_user: CurrentUser = Depends(get_current_user)
):
    """
    Invalidează cache

    Args:
        company_id: Opțional - invalidează doar pentru această companie
        cache_type: Opțional - invalidează doar acest tip de cache

    Returns:
        Message de confirmare
    """
    try:
        cache = get_cache()
        if not cache:
            raise HTTPException(status_code=503, detail="Cache not initialized")

        await cache.invalidate(
            company_id=request.company_id,
            cache_type=request.cache_type
        )

        if request.company_id and request.cache_type:
            message = f"Cache invalidated for company {request.company_id}, type {request.cache_type}"
        elif request.company_id:
            message = f"Cache invalidated for company {request.company_id}"
        elif request.cache_type:
            message = f"Cache invalidated for type {request.cache_type}"
        else:
            message = "All cache invalidated"

        return {
            "success": True,
            "message": message,
            "invalidated_at": datetime.now().isoformat()
        }

    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Error invalidating cache: {str(e)}")


@router.post("/toggle-user")
async def toggle_user_cache(
    request: ToggleUserCacheRequest,
    current_user: CurrentUser = Depends(get_current_user)
):
    """
    Toggle cache per-user

    Permite utilizatorului să activeze/dezactiveze cache-ul pentru el
    Folosit pentru A/B testing și comparații de performanță

    Args:
        enabled: True pentru activare, False pentru dezactivare

    Returns:
        Noul status
    """
    try:
        cache = get_cache()
        if not cache:
            raise HTTPException(status_code=503, detail="Cache not initialized")

        await cache.set_user_cache_enabled(current_user.username, request.enabled)

        return {
            "success": True,
            "username": current_user.username,
            "cache_enabled": request.enabled,
            "message": f"Cache {'enabled' if request.enabled else 'disabled'} for user {current_user.username}"
        }

    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Error toggling user cache: {str(e)}")


@router.post("/toggle-global")
async def toggle_global_cache(
    request: ToggleGlobalCacheRequest,
    current_user: CurrentUser = Depends(get_current_user)
):
    """
    Toggle cache global (ADMIN only)

    Activează/dezactivează cache-ul la nivel global pentru toți utilizatorii

    Args:
        enabled: True pentru activare, False pentru dezactivare

    Returns:
        Noul status global
    """
    try:
        # TODO: Add admin permission check
        # For now, allow any authenticated user

        cache = get_cache()
        if not cache:
            raise HTTPException(status_code=503, detail="Cache not initialized")

        # Update config (NOTE: This is runtime only, .env needs manual update)
        cache.config.enabled = request.enabled

        return {
            "success": True,
            "global_enabled": request.enabled,
            "message": f"Cache {'enabled' if request.enabled else 'disabled'} globally",
            "note": "This change is runtime only. Update .env CACHE_ENABLED for persistence."
        }

    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Error toggling global cache: {str(e)}")


@router.post("/toggle-auto-invalidate")
async def toggle_auto_invalidation(
    request: ToggleAutoInvalidateRequest,
    current_user: CurrentUser = Depends(get_current_user)
):
    """
    Toggle auto-invalidation monitoring

    Activează/dezactivează monitorizarea automată a {schema}.act
    pentru invalidarea cache-ului când se detectează modificări

    Args:
        enabled: True pentru activare, False pentru dezactivare

    Returns:
        Noul status auto-invalidation
    """
    try:
        # TODO: Add admin permission check
        # For now, allow any authenticated user

        await toggle_event_monitor(request.enabled)

        return {
            "success": True,
            "auto_invalidate_enabled": request.enabled,
            "message": f"Auto-invalidation {'enabled' if request.enabled else 'disabled'}",
            "note": "Monitors max(id_act) in {schema}.act tables for changes"
        }

    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Error toggling auto-invalidation: {str(e)}")


@router.get("/health")
async def cache_health():
    """
    Health check pentru sistemul de cache

    Returns:
        Status cache, mărime, și uptime
    """
    try:
        cache = get_cache()
        if not cache:
            return {
                "status": "not_initialized",
                "enabled": False
            }

        stats = await cache.get_stats()
        monitor = get_event_monitor()

        return {
            "status": "healthy",
            "enabled": cache.config.enabled,
            "cache_type": cache.config.cache_type,
            "memory_size": stats.get('memory', {}).get('size', 0),
            "sqlite_size": stats.get('sqlite', {}).get('active_entries', 0),
            "auto_invalidate_running": monitor.running if monitor else False
        }

    except Exception as e:
        return {
            "status": "error",
            "error": str(e)
        }
