"""
Dynamic Execution Service.

Handles creation and execution of dynamically defined agents/teams
without pre-creating entity records in the database.
"""

from typing import Dict, Any, Optional
import uuid
from datetime import datetime, timezone
import structlog

from sqlalchemy.orm import Session

from control_plane_api.app.models.execution import Execution
from control_plane_api.app.models.associations import ExecutionParticipant
from control_plane_api.app.models.worker import WorkerQueue
from control_plane_api.app.lib.temporal_client import get_temporal_client
from control_plane_api.app.services.queue_resolution_service import queue_resolution_service

logger = structlog.get_logger()


class DynamicExecutionService:
    """Service for managing dynamic agent/team executions"""

    async def create_and_execute(
        self,
        db: Session,
        prompt: str,
        entity_definition: Dict[str, Any],
        organization_id: str,
        user_metadata: Dict[str, Any],
        control_plane_url: str,
        api_key: str,
        worker_queue_id: Optional[str] = None,
        meta_agent_session_id: Optional[str] = None,
        is_shared: bool = False,
        privacy_level: str = "private",
    ) -> Dict[str, Any]:
        """
        Create and execute a dynamic agent or team.

        Args:
            db: Database session
            prompt: User prompt for execution
            entity_definition: Agent/team configuration
            organization_id: Organization ID
            user_metadata: User information
            control_plane_url: Control Plane base URL
            api_key: API key for authentication
            worker_queue_id: Optional worker queue (auto-resolved if None)
            meta_agent_session_id: Optional meta agent session ID
            is_shared: Whether to share execution
            privacy_level: Privacy level (private/org/public)

        Returns:
            {
                "execution_id": str,
                "workflow_id": str,
                "status": str,
                "entity_id": str,
                "worker_queue_id": str,
                "message": str
            }
        """
        entity_type = entity_definition.get("entity_type", "agent")
        runtime = entity_definition.get("runtime", "claude_code")

        # STEP 1: Resolve worker queue if not provided
        if not worker_queue_id:
            logger.info("Auto-resolving worker queue for dynamic execution")
            queue_result = await queue_resolution_service.resolve_queue(
                db=db,
                prompt=prompt,
                organization_id=organization_id,
                preferred_runtime=runtime,
            )
            worker_queue_id = queue_result["worker_queue_id"]
            logger.info(
                "Auto-selected worker queue",
                queue_id=worker_queue_id,
                queue_name=queue_result["worker_queue_name"],
            )

        # STEP 2: Validate worker queue
        worker_queue = db.query(WorkerQueue).filter(
            WorkerQueue.id == worker_queue_id,
            WorkerQueue.organization_id == organization_id,
            WorkerQueue.status == "active",
        ).first()

        if not worker_queue:
            raise ValueError(f"Worker queue {worker_queue_id} not found or inactive")

        # STEP 3: Generate ephemeral IDs
        entity_id = str(uuid.uuid4())
        execution_id = str(uuid.uuid4())

        # STEP 4: Build execution metadata
        execution_metadata = {
            "is_dynamic_execution": True,
            "dynamic_entity_definition": entity_definition,
            "meta_agent_session_id": meta_agent_session_id,
            "meta_agent_user_id": user_metadata.get("user_id"),
            "is_shared": is_shared,
            "privacy_level": privacy_level,
            "share_requests": [],
            "auto_selected_queue": worker_queue_id is None,
        }

        # STEP 5: Create execution record
        execution = Execution(
            id=execution_id,
            organization_id=organization_id,
            execution_type=entity_type.upper(),
            entity_id=entity_id,  # Ephemeral, not in agents/teams table
            entity_name=entity_definition.get("name") or f"Dynamic {entity_type}",
            runner_name="dynamic-execution",  # Runner name for dynamic executions
            prompt=prompt,
            system_prompt=entity_definition.get("system_prompt"),
            status="PENDING",
            worker_queue_id=worker_queue_id,
            task_queue_name=worker_queue.name,
            user_id=user_metadata.get("user_id"),
            user_name=user_metadata.get("user_name"),
            user_email=user_metadata.get("user_email"),
            user_avatar=user_metadata.get("user_avatar"),
            execution_metadata=execution_metadata,
            trigger_source="user",  # Triggered by user via meta agent
        )
        db.add(execution)
        db.commit()

        logger.info(
            "Created dynamic execution record",
            execution_id=execution_id,
            entity_type=entity_type,
            organization_id=organization_id,
        )

        # STEP 6: Add creator as owner participant
        participant = ExecutionParticipant(
            execution_id=execution_id,
            organization_id=organization_id,
            user_id=user_metadata.get("user_id"),
            user_name=user_metadata.get("user_name"),
            user_email=user_metadata.get("user_email"),
            user_avatar=user_metadata.get("user_avatar"),
            role="owner",
        )
        db.add(participant)
        db.commit()

        # STEP 7: Build configuration for workflow
        agent_config = entity_definition.get("configuration", {}).copy()

        # For teams: build native subagent configuration
        if entity_type == "team" and entity_definition.get("subagents"):
            agents_config = {}

            for idx, subagent in enumerate(entity_definition["subagents"]):
                subagent_id = f"subagent_{idx}"
                agents_config[subagent_id] = {
                    "description": subagent.get("name") or f"Subagent {idx}",
                    "prompt": subagent.get("system_prompt"),
                    "model": subagent.get("model_id"),
                    # Tools will be resolved from skill_ids by runtime
                }

            agent_config["runtime_config"] = {
                "agents": agents_config
            }

        # STEP 8: Start dedicated Temporal workflow for dynamic execution
        temporal_client = await get_temporal_client()

        # Import the dedicated workflow
        from control_plane_api.app.workflows.dynamic_agent_execution import (
            DynamicAgentExecutionWorkflow,
            DynamicAgentExecutionInput,
        )

        workflow_input = DynamicAgentExecutionInput(
            execution_id=execution_id,
            entity_id=entity_id,
            entity_type=entity_type,
            organization_id=organization_id,
            prompt=prompt,
            system_prompt=entity_definition.get("system_prompt"),
            model_id=entity_definition.get("model_id", "kubiya/claude-sonnet-4"),
            model_config=entity_definition.get("model_params", {}),
            agent_config=agent_config,
            mcp_servers=entity_definition.get("mcp_servers", {}),
            skill_ids=entity_definition.get("skill_ids", []),
            user_metadata=user_metadata,
            runtime_type=runtime,
            control_plane_url=control_plane_url,
            api_key=api_key,
        )

        workflow_handle = await temporal_client.start_workflow(
            DynamicAgentExecutionWorkflow.run,
            workflow_input,
            id=f"dynamic-execution-{execution_id}",
            task_queue=worker_queue.name,
        )

        logger.info(
            "Started dynamic execution workflow",
            execution_id=execution_id,
            workflow_id=workflow_handle.id,
            task_queue=worker_queue.name,
        )

        # STEP 9: Emit WebSocket event (non-blocking)
        try:
            from control_plane_api.app.routers.websocket_executions_status import (
                broadcast_status_update
            )
            await broadcast_status_update(
                organization_id,
                {
                    "type": "meta_agent_linked",
                    "execution_id": execution_id,
                    "meta_agent_session_id": meta_agent_session_id,
                    "timestamp": datetime.now(timezone.utc).isoformat(),
                }
            )
        except Exception as e:
            logger.warning("Failed to broadcast WebSocket event", error=str(e))

        return {
            "execution_id": execution_id,
            "workflow_id": workflow_handle.id,
            "status": "PENDING",
            "entity_id": entity_id,
            "worker_queue_id": worker_queue_id,
            "message": "Dynamic execution started successfully",
        }


# Singleton instance
dynamic_execution_service = DynamicExecutionService()
