"""
Dynamic Executions Router.

Thin HTTP layer for dynamic agent/team execution endpoints.
Business logic is handled by services.
"""

from fastapi import APIRouter, Depends, HTTPException, Request
from sqlalchemy.orm import Session
import structlog

from control_plane_api.app.middleware.auth import get_current_organization
from control_plane_api.app.database import get_db
from control_plane_api.app.schemas.execution_schemas import (
    DynamicExecutionRequest,
    DynamicExecutionResponse,
    QueueResolutionRequest,
    QueueResolutionResponse,
)
from control_plane_api.app.services.queue_resolution_service import queue_resolution_service
from control_plane_api.app.services.dynamic_execution_service import dynamic_execution_service
from control_plane_api.app.services.access_control_service import access_control_service
from control_plane_api.app.observability import instrument_endpoint
from control_plane_api.app.lib.validation.user_id_validation import log_if_invalid_user_id

logger = structlog.get_logger()

router = APIRouter(prefix="/dynamic-executions", tags=["Dynamic Executions"])


@router.post("/resolve-queue", response_model=QueueResolutionResponse)
@instrument_endpoint("dynamic_executions.resolve_queue")
async def resolve_worker_queue(
    request_data: QueueResolutionRequest,
    organization: dict = Depends(get_current_organization),
    db: Session = Depends(get_db),
):
    """
    Intelligent worker queue resolution based on task prompt.

    Analyzes the task and recommends the optimal worker queue
    based on capabilities, current load, and relevance.
    """
    try:
        result = await queue_resolution_service.resolve_queue(
            db=db,
            prompt=request_data.prompt,
            organization_id=organization["id"],
            preferred_runtime=request_data.preferred_runtime or "claude_code",
        )

        return QueueResolutionResponse(**result)

    except ValueError as e:
        raise HTTPException(status_code=404, detail=str(e))
    except Exception as e:
        logger.error(
            "Queue resolution failed",
            organization_id=organization["id"],
            error=str(e),
        )
        raise HTTPException(
            status_code=500,
            detail="Failed to resolve worker queue",
        )


@router.post("/execute", response_model=DynamicExecutionResponse)
@instrument_endpoint("dynamic_executions.execute")
async def execute_dynamic(
    request_data: DynamicExecutionRequest,
    request: Request,
    organization: dict = Depends(get_current_organization),
    db: Session = Depends(get_db),
):
    """
    Execute an agent or team dynamically without pre-creating entity.

    Creates an ephemeral agent/team and executes it immediately.
    The entity is not persisted to the agents/teams table.

    Workflow:
    1. Auto-resolve worker queue if not provided
    2. Generate ephemeral entity_id
    3. Store full entity definition in execution_metadata
    4. Start dedicated Temporal workflow
    5. Link to meta_agent_session_id if provided
    """
    try:
        # Extract user metadata
        user_metadata = {
            "user_id": organization.get("user_id"),
            "user_email": organization.get("user_email"),
            "user_name": organization.get("user_name"),
            "user_avatar": organization.get("user_avatar"),
        }

        # Get API key from header
        api_key = request.headers.get("Authorization", "").replace("Bearer ", "")

        # Execute via service
        result = await dynamic_execution_service.create_and_execute(
            db=db,
            prompt=request_data.prompt,
            entity_definition=request_data.entity.model_dump(),
            organization_id=organization["id"],
            user_metadata=user_metadata,
            control_plane_url=str(request.base_url),
            api_key=api_key,
            worker_queue_id=request_data.worker_queue_id,
            meta_agent_session_id=request_data.meta_agent_session_id,
            is_shared=request_data.is_shared,
            privacy_level=request_data.privacy_level,
        )

        return DynamicExecutionResponse(**result)

    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))
    except Exception as e:
        logger.error(
            "Dynamic execution failed",
            organization_id=organization["id"],
            error=str(e),
        )
        raise HTTPException(
            status_code=500,
            detail="Failed to start dynamic execution",
        )


# ==================== Access Control Endpoints ====================


@router.post("/executions/{execution_id}/request-access")
@instrument_endpoint("dynamic_executions.request_access")
async def request_access(
    execution_id: str,
    organization: dict = Depends(get_current_organization),
    db: Session = Depends(get_db),
):
    """Request access to a private execution"""
    try:
        if organization["user_id"] is None:
            logger.warning(
                "missing_user_id_at_access_control",
                action="request_access",
                execution_id=execution_id,
                org_id=organization.get("id"),
            )
        log_if_invalid_user_id(organization["user_id"], source="access_control_request", execution_id=execution_id)
        result = await access_control_service.request_access(
            db=db,
            execution_id=execution_id,
            organization_id=organization["id"],
            user_id=organization["user_id"],
            user_name=organization.get("user_name", ""),
            user_email=organization.get("user_email", ""),
        )
        return result
    except ValueError as e:
        raise HTTPException(status_code=404, detail=str(e))
    except Exception as e:
        logger.error("Access request failed", error=str(e))
        raise HTTPException(status_code=500, detail="Failed to request access")


@router.post("/executions/{execution_id}/grant-access/{user_id}")
@instrument_endpoint("dynamic_executions.grant_access")
async def grant_access(
    execution_id: str,
    user_id: str,
    organization: dict = Depends(get_current_organization),
    db: Session = Depends(get_db),
):
    """Grant access to a user (owner only)"""
    try:
        if organization["user_id"] is None:
            logger.warning(
                "missing_user_id_at_access_control",
                action="grant_access",
                execution_id=execution_id,
                org_id=organization.get("id"),
            )
        log_if_invalid_user_id(organization["user_id"], source="access_control_grant", execution_id=execution_id)
        result = await access_control_service.grant_access(
            db=db,
            execution_id=execution_id,
            organization_id=organization["id"],
            owner_user_id=organization["user_id"],
            target_user_id=user_id,
        )
        return result
    except PermissionError as e:
        raise HTTPException(status_code=403, detail=str(e))
    except ValueError as e:
        raise HTTPException(status_code=404, detail=str(e))
    except Exception as e:
        logger.error("Grant access failed", error=str(e))
        raise HTTPException(status_code=500, detail="Failed to grant access")


@router.post("/executions/{execution_id}/deny-access/{user_id}")
@instrument_endpoint("dynamic_executions.deny_access")
async def deny_access(
    execution_id: str,
    user_id: str,
    reason: str = None,
    organization: dict = Depends(get_current_organization),
    db: Session = Depends(get_db),
):
    """Deny access request (owner only)"""
    try:
        if organization["user_id"] is None:
            logger.warning(
                "missing_user_id_at_access_control",
                action="deny_access",
                execution_id=execution_id,
                org_id=organization.get("id"),
            )
        log_if_invalid_user_id(organization["user_id"], source="access_control_deny", execution_id=execution_id)
        result = await access_control_service.deny_access(
            db=db,
            execution_id=execution_id,
            owner_user_id=organization["user_id"],
            target_user_id=user_id,
            reason=reason,
        )
        return result
    except PermissionError as e:
        raise HTTPException(status_code=403, detail=str(e))
    except ValueError as e:
        raise HTTPException(status_code=404, detail=str(e))
    except Exception as e:
        logger.error("Deny access failed", error=str(e))
        raise HTTPException(status_code=500, detail="Failed to deny access")


# ==================== Monitoring Endpoints ====================


@router.get("/queue-resolution/metrics")
@instrument_endpoint("dynamic_executions.queue_resolution_metrics")
async def get_queue_resolution_metrics(
    organization: dict = Depends(get_current_organization),
):
    """Get queue resolution service performance metrics"""
    try:
        metrics = queue_resolution_service.get_metrics()
        return {
            "status": "ok",
            "metrics": metrics,
            "organization_id": organization["id"],
        }
    except Exception as e:
        logger.error("Failed to get metrics", error=str(e))
        raise HTTPException(status_code=500, detail="Failed to retrieve metrics")
