#
# Copyright 2026 The Dapr Authors
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#     http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

"""Agent-based orchestration strategy using LLM planning and decision-making.

This strategy implements plan-based multi-agent orchestration where an LLM:
1. Generates a structured execution plan (Turn 1)
2. Selects the next agent and step based on plan progression
3. Validates step completion and updates plan status
4. Generates a final summary when orchestration completes

This is the most sophisticated orchestration mode, suitable for complex
tasks requiring adaptive planning and progress tracking.

Note: For AgentOrchestrationStrategy, most logic is handled directly in the
orchestration_workflow due to the need for async LLM activity calls. The
strategy class serves primarily as a marker and configuration holder.
"""

import logging
from typing import Any, Dict

from dapr_agents.agents.orchestration.strategy import OrchestrationStrategy

logger = logging.getLogger(__name__)


class AgentOrchestrationStrategy(OrchestrationStrategy):
    """Plan-based orchestration using LLM for planning and decision-making.

    This strategy maintains an execution plan with steps and substeps,
    using an LLM to:
    - Generate the initial plan
    - Select the next agent/step at each turn
    - Validate and update plan progress
    - Generate final summaries

    State Schema:
        {
            "task": str,                     # Original task
            "agents": Dict,                  # Available agents
            "plan": List[Dict],              # List of PlanStep objects
            "task_history": List[Dict],      # Agent execution results
            "verdict": Optional[str],        # continue/completed/failed
            "current_step_id": int,          # Current step being executed
            "current_substep_id": float,     # Current substep being executed
            "last_agent": str,               # Last agent that executed
            "last_result": str               # Last execution result
        }

    Note: The actual orchestration logic is implemented directly in the
    orchestration_workflow method of DurableAgent due to the need for
    async activity calls. This class serves as a marker to identify
    agent-based orchestration mode.
    """

    def initialize(self, ctx: Any, task: str, agents: Dict[str, Any]) -> Dict[str, Any]:
        """Initialize orchestration state.

        For AgentOrchestrationStrategy, initialization is handled in orchestration_workflow.
        This method is kept for interface compatibility.

        Args:
            ctx: Activity context
            task: Task description
            agents: Available agents

        Returns:
            Initial state structure
        """
        return {
            "task": task,
            "agents": agents,
            "plan": [],
            "task_history": [],
            "verdict": None,
        }

    def select_next_agent(
        self, ctx: Any, state: Dict[str, Any], turn: int
    ) -> Dict[str, Any]:
        """Select next agent and instruction.

        For AgentOrchestrationStrategy, selection is handled in orchestration_workflow.
        This method is kept for interface compatibility.

        Args:
            ctx: Activity context
            state: Current state
            turn: Current turn number

        Returns:
            Action dict placeholder
        """
        return {
            "agent": "",
            "instruction": "",
            "metadata": {},
        }

    def process_response(
        self, ctx: Any, state: Dict[str, Any], response: Dict[str, Any]
    ) -> Dict[str, Any]:
        """Process agent response.

        For AgentOrchestrationStrategy, processing is handled in orchestration_workflow.
        This method is kept for interface compatibility.

        Args:
            ctx: Activity context
            state: Current state
            response: Agent response

        Returns:
            Updated state placeholder
        """
        return {
            "updated_state": state,
            "verdict": "continue",
        }

    def should_continue(
        self, state: Dict[str, Any], turn: int, max_iterations: int
    ) -> bool:
        """Check if orchestration should continue.

        For AgentOrchestrationStrategy, continuation is handled in orchestration_workflow.
        This method is kept for interface compatibility.

        Args:
            state: Current state
            turn: Current turn
            max_iterations: Max iterations

        Returns:
            True (actual logic in workflow)
        """
        return True

    def finalize(self, ctx: Any, state: Dict[str, Any]) -> Dict[str, Any]:
        """Generate final summary.

        For AgentOrchestrationStrategy, finalization is handled in orchestration_workflow.
        This method is kept for interface compatibility.

        Args:
            ctx: Activity context
            state: Final state

        Returns:
            Final message placeholder
        """
        return {
            "role": "assistant",
            "content": "Orchestration completed.",
            "name": getattr(self, "orchestrator_name", "AgentOrchestrator"),
        }
