"""Queue selection service for intelligent routing of executions."""

from typing import Optional
from sqlalchemy.orm import Session
import structlog
from fastapi import HTTPException, status

from control_plane_api.app.models.worker import WorkerQueue
from control_plane_api.app.routers.worker_queues import get_active_workers_from_redis

logger = structlog.get_logger()


async def auto_select_worker_queue(
    organization_id: str,
    environment_id: Optional[str] = None,
    min_workers: int = 1,
    db: Session = None,
) -> Optional[WorkerQueue]:
    """
    Automatically select the best available worker queue.

    Selection criteria (in order):
    1. Status = 'active'
    2. Has at least min_workers active workers
    3. Matches environment_id (if specified)
    4. Has highest available capacity

    Returns:
        WorkerQueue object, or None if no suitable queue found
    """

    # Query active queues
    query = (
        db.query(WorkerQueue)
        .filter(
            WorkerQueue.organization_id == organization_id,
            WorkerQueue.status == 'active',
            WorkerQueue.ephemeral == False  # Don't auto-select ephemeral queues
        )
    )

    if environment_id:
        query = query.filter(WorkerQueue.environment_id == environment_id)

    queues = query.all()

    if not queues:
        logger.warning("no_active_queues", org_id=organization_id, env_id=environment_id)
        return None

    # Get active worker counts from Redis
    active_workers = await get_active_workers_from_redis(organization_id, db=db)

    worker_counts = {}
    for worker_id, worker_data in active_workers.items():
        queue_id = worker_data.get("worker_queue_id")
        if queue_id:
            worker_counts[queue_id] = worker_counts.get(queue_id, 0) + 1

    # Filter and sort by capacity
    healthy_queues = []
    for queue in queues:
        count = worker_counts.get(str(queue.id), 0)
        if count >= min_workers:
            healthy_queues.append((queue, count))

    if not healthy_queues:
        logger.warning("no_healthy_queues", org_id=organization_id, env_id=environment_id)
        return None

    # Sort by worker count (descending) - use queue with most capacity
    healthy_queues.sort(key=lambda x: x[1], reverse=True)

    selected_queue, worker_count = healthy_queues[0]

    logger.info(
        "queue_auto_selected",
        queue_id=str(selected_queue.id),
        queue_name=selected_queue.name,
        active_workers=worker_count,
        org_id=organization_id,
    )

    return selected_queue


def validate_worker_queue(
    queue_id: str,
    organization_id: str,
    db: Session,
) -> WorkerQueue:
    """
    Validate that a worker queue exists and is active.

    Raises HTTPException if invalid.
    """

    queue = (
        db.query(WorkerQueue)
        .filter(
            WorkerQueue.id == queue_id,
            WorkerQueue.organization_id == organization_id
        )
        .first()
    )

    if not queue:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"Worker queue not found: {queue_id}"
        )

    if queue.status != "active":
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"Worker queue is not active: {queue.name}"
        )

    return queue
