"""
Cleanup activities for ephemeral worker queues.

These activities handle automatic cleanup of temporary/on-demand worker queues
that have exceeded their TTL or completed their parent execution.
"""

import structlog
from datetime import datetime, timedelta
from temporalio import activity
from typing import List, Dict

logger = structlog.get_logger()


@activity.defn(name="cleanup_ephemeral_queues")
async def cleanup_ephemeral_queues() -> Dict[str, int]:
    """
    Scan and cleanup ephemeral worker queues that should be deleted.

    Cleanup criteria:
    1. Queue is marked as ephemeral=true
    2. TTL has expired (created_at + auto_cleanup_after_seconds < now)
    3. No active workers in the queue
    4. Parent execution (if set) is completed/failed

    Returns:
        Dict with cleanup statistics: {
            "scanned": int,
            "cleaned": int,
            "skipped": int,
            "errors": int
        }
    """
    import os
    import httpx
    from sqlalchemy.orm import Session
    from control_plane_api.app.database import get_session_local
    from control_plane_api.app.models.worker import WorkerQueue, WorkerHeartbeat

    # Get database session
    SessionLocal = get_session_local()
    db: Session = SessionLocal()

    stats = {
        "scanned": 0,
        "cleaned": 0,
        "skipped": 0,
        "errors": 0,
    }

    try:
        # Find all ephemeral queues
        ephemeral_queues = (
            db.query(WorkerQueue)
            .filter(WorkerQueue.ephemeral == True)
            .all()
        )

        stats["scanned"] = len(ephemeral_queues)

        if not ephemeral_queues:
            logger.info("no_ephemeral_queues_to_cleanup")
            return stats

        logger.info(
            "scanning_ephemeral_queues",
            count=stats["scanned"]
        )

        now = datetime.utcnow()

        for queue in ephemeral_queues:
            try:
                # Check if TTL has expired
                if queue.auto_cleanup_after_seconds:
                    expires_at = queue.created_at + timedelta(seconds=queue.auto_cleanup_after_seconds)
                    if now < expires_at:
                        logger.debug(
                            "queue_not_expired_yet",
                            queue_id=str(queue.id),
                            queue_name=queue.name,
                            expires_at=expires_at.isoformat(),
                        )
                        stats["skipped"] += 1
                        continue

                # Check for active workers
                active_workers = (
                    db.query(WorkerHeartbeat)
                    .filter(
                        WorkerHeartbeat.worker_queue_id == queue.id,
                        WorkerHeartbeat.status.in_(["active", "idle", "busy"])
                    )
                    .count()
                )

                if active_workers > 0:
                    logger.debug(
                        "queue_has_active_workers",
                        queue_id=str(queue.id),
                        queue_name=queue.name,
                        active_workers=active_workers,
                    )
                    stats["skipped"] += 1
                    continue

                # Check parent execution status if set
                if queue.parent_execution_id:
                    # Query control plane API to check execution status
                    control_plane_url = os.environ.get("CONTROL_PLANE_URL")
                    kubiya_api_key = os.environ.get("KUBIYA_API_KEY")

                    if control_plane_url and kubiya_api_key:
                        try:
                            async with httpx.AsyncClient(timeout=10.0) as client:
                                response = await client.get(
                                    f"{control_plane_url}/api/v1/executions/{queue.parent_execution_id}",
                                    headers={"Authorization": f"Bearer {kubiya_api_key}"}
                                )

                                if response.status_code == 200:
                                    execution = response.json()
                                    status = execution.get("status")

                                    # Only cleanup if execution is completed or failed
                                    if status not in ["completed", "failed", "cancelled"]:
                                        logger.debug(
                                            "parent_execution_still_running",
                                            queue_id=str(queue.id),
                                            queue_name=queue.name,
                                            parent_execution_id=queue.parent_execution_id,
                                            execution_status=status,
                                        )
                                        stats["skipped"] += 1
                                        continue
                        except Exception as e:
                            logger.warning(
                                "failed_to_check_parent_execution",
                                queue_id=str(queue.id),
                                error=str(e)
                            )
                            # Continue with cleanup anyway if API check fails

                # All checks passed - delete the queue
                logger.info(
                    "cleaning_up_ephemeral_queue",
                    queue_id=str(queue.id),
                    queue_name=queue.name,
                    age_seconds=(now - queue.created_at).total_seconds(),
                )

                db.delete(queue)
                db.commit()

                stats["cleaned"] += 1

            except Exception as e:
                logger.error(
                    "failed_to_cleanup_queue",
                    queue_id=str(queue.id),
                    queue_name=queue.name,
                    error=str(e),
                )
                stats["errors"] += 1
                db.rollback()

        logger.info(
            "ephemeral_queue_cleanup_complete",
            **stats
        )

        return stats

    except Exception as e:
        logger.error("cleanup_activity_failed", error=str(e))
        raise
    finally:
        db.close()
