"""Background cleanup tasks."""

import asyncio
from datetime import datetime, timedelta
from uuid import UUID
import time

from celery import shared_task

from src.core.celery_app import celery_app
from src.core.database import AsyncSessionLocal
from src.core.cache import cache_manager
from src.core.logging_config import get_logger, set_correlation_id
from src.core.monitoring import metrics
from src.repositories.report import report_repository
from src.services.report_service import report_service


logger = get_logger(__name__)


@celery_app.task(
    bind=True,
    time_limit=1800,  # 30 minutes
    rate_limit="1/h",  # Run once per hour
)
def cleanup_old_reports(self, max_age_days: int = 30):
    """Clean up old report files and database entries.

    Args:
        max_age_days: Maximum age of reports in days
    """
    correlation_id = set_correlation_id()
    start_time = datetime.utcnow()

    logger.info(
        "Starting old reports cleanup",
        extra={"max_age_days": max_age_days, "correlation_id": correlation_id},
    )

    try:
        # Run cleanup
        deleted_count = asyncio.run(_cleanup_reports_async(max_age_days))

        duration = (datetime.utcnow() - start_time).total_seconds()

        logger.info(
            "Reports cleanup completed",
            extra={
                "deleted_count": deleted_count,
                "duration_seconds": duration,
            },
        )

        return {
            "status": "completed",
            "deleted_count": deleted_count,
            "duration_seconds": duration,
        }

    except Exception as exc:
        logger.exception("Reports cleanup failed")
        raise self.retry(exc=exc, countdown=3600)


async def _cleanup_reports_async(max_age_days: int) -> int:
    """Async helper for report cleanup."""
    async with AsyncSessionLocal() as db:
        try:
            # Cleanup files
            deleted_count = await report_service.cleanup_old_reports(max_age_days)

            # Cleanup database entries
            cutoff_date = datetime.now() - timedelta(days=max_age_days)
            db_deleted = await report_repository.delete_old_reports(db, cutoff_date)

            await db.commit()

            return deleted_count + db_deleted

        except Exception as e:
            await db.rollback()
            raise


@celery_app.task(
    bind=True,
    time_limit=600,  # 10 minutes
)
def cleanup_expired_sessions(self):
    """Clean up expired user sessions from cache."""
    correlation_id = set_correlation_id()

    logger.info(
        "Starting expired sessions cleanup", extra={"correlation_id": correlation_id}
    )

    try:
        # Initialize cache manager
        asyncio.run(cache_manager.initialize())

        # Delete session pattern
        deleted = asyncio.run(cache_manager.delete_pattern("session:*"))

        logger.info(
            "Expired sessions cleanup completed",
            extra={"deleted_sessions": deleted},
        )

        return {"status": "completed", "deleted_sessions": deleted}

    except Exception as exc:
        logger.exception("Sessions cleanup failed")
        raise self.retry(exc=exc, countdown=1800)


@celery_app.task(
    bind=True,
    time_limit=300,  # 5 minutes
)
def cleanup_stale_cache(self, pattern: str = "*"):
    """Clean up stale cache entries.

    Args:
        pattern: Cache key pattern to clean up
    """
    correlation_id = set_correlation_id()

    logger.info(
        "Starting stale cache cleanup",
        extra={"pattern": pattern, "correlation_id": correlation_id},
    )

    try:
        asyncio.run(cache_manager.initialize())

        # Get cache stats before cleanup
        stats_before = asyncio.run(cache_manager.get_stats())

        # Clean up expired keys (Redis does this automatically, but we can force it)
        # This is mostly for checking cache health
        stats_after = asyncio.run(cache_manager.get_stats())

        logger.info(
            "Cache cleanup completed",
            extra={
                "stats_before": stats_before,
                "stats_after": stats_after,
            },
        )

        return {
            "status": "completed",
            "stats": stats_after,
        }

    except Exception as exc:
        logger.exception("Cache cleanup failed")
        raise self.retry(exc=exc, countdown=3600)


@celery_app.task(
    bind=True,
    time_limit=60,
)
def health_check_task(self):
    """Periodic health check task.

    This task runs frequently to verify system health.
    """
    correlation_id = set_correlation_id()

    health_status = {
        "timestamp": datetime.utcnow().isoformat(),
        "status": "healthy",
        "checks": {},
    }

    # Check database connectivity
    try:
        asyncio.run(_check_database())
        health_status["checks"]["database"] = "healthy"
    except Exception as e:
        health_status["checks"]["database"] = f"unhealthy: {str(e)}"
        health_status["status"] = "degraded"
        logger.error(f"Database health check failed: {e}")

    # Check cache connectivity
    try:
        asyncio.run(cache_manager.initialize())
        stats = asyncio.run(cache_manager.get_stats())
        health_status["checks"]["cache"] = "healthy"
        health_status["checks"]["cache_stats"] = stats
    except Exception as e:
        health_status["checks"]["cache"] = f"unhealthy: {str(e)}"
        health_status["status"] = "degraded"
        logger.error(f"Cache health check failed: {e}")

    # Log health status
    if health_status["status"] == "healthy":
        logger.debug("Health check passed", extra=health_status)
    else:
        logger.warning("Health check detected issues", extra=health_status)

    return health_status


async def _check_database():
    """Check database connectivity."""
    async with AsyncSessionLocal() as db:
        from sqlalchemy import text

        result = await db.execute(text("SELECT 1"))
        result.scalar()
