"""Planner Agent."""

from typing import Any, Dict, List

from dbgpt._private.pydantic import Field

from ..core.agent import AgentMessage
from ..core.base_agent import ConversableAgent
from .plan_action import PlanAction


class PlannerAgent(ConversableAgent):
    """Planner Agent.

    Planner agent, realizing task goal planning decomposition through LLM.
    """

    agents: List[ConversableAgent] = Field(default_factory=list)

    profile: str = "Planner"
    goal_zh: str = (
        "理解下面每个智能体(agent)和他们的能力，使用给出的资源，通过协调智能体来解决"
        "用户问题。 请发挥你LLM的知识和理解能力，理解用户问题的意图和目标，生成一个可以在没有用户帮助"
        "下，由智能体协作完成目标的任务计划。"
    )
    goal: str = (
        "Understand each of the following intelligent agents and their "
        "capabilities, using the provided resources, solve user problems by "
        "coordinating intelligent agents. Please utilize your LLM's knowledge "
        "and understanding ability to comprehend the intent and goals of the "
        "user's problem, generating a task plan that can be completed through"
        " the collaboration of intelligent agents without user assistance."
    )
    expand_prompt_zh: str = "可用智能体(agent):\n {agents}"
    expand_prompt: str = "Available Intelligent Agents:\n {agents}"

    constraints_zh: List[str] = [
        "任务计划的每个步骤都应该是为了推进解决用户目标而存在，不要生成无意义的任务步骤，确保每个步骤内目标明确内容完整。",
        "关注任务计划每个步骤的依赖关系和逻辑，被依赖步骤要考虑被依赖的数据，是否能基于当前目标得到，如果不能请在目标中提示要生成被依赖数据。",
        "每个步骤都是一个独立可完成的目标，一定要确保逻辑和信息完整，不要出现类似:"
        "'Analyze the retrieved issues data'这样目标不明确，不知道具体要分析啥内容的步骤",
        "请确保只使用上面提到的智能体，并且可以只使用其中需要的部分，严格根据描述能力和限制分配给合适的步骤，每个智能体都可以重复使用。",
        "根据用户目标的实际需要使用提供的资源来协助生成计划步骤，不要使用不需要的资源。",
        "每个步骤最好只使用一种资源完成一个子目标，如果当前目标可以分解为同类型的多个子任务，可以生成相互不依赖的并行任务。",
        "数据资源可以被合适的智能体加载使用，不用考虑数据资源的加载链接问题",
        "尽量合并有顺序依赖的连续相同步骤,如果用户目标无拆分必要，可以生成内容为用户目标的单步任务。",
        "仔细检查计划，确保计划完整的包含了用户问题所涉及的所有信息，并且最终能完成目标，确认每个步骤是否包含了需要用到的资源信息,如URL、资源名等. ",
    ]
    constraints: List[str] = [
        "Every step of the task plan should exist to advance towards solving the user's"
        " goals. Do not generate meaningless task steps; ensure that each step has a "
        "clear goal and its content is complete.",
        "Pay attention to the dependencies and logic of each step in the task plan. "
        "For the steps that are depended upon, consider the data they depend on and "
        "whether it can be obtained based on the current goal. If it cannot be obtained"
        ", please indicate in the goal that the dependent data needs to be generated.",
        "Each step must be an independently achievable goal. Ensure that the logic and"
        " information are complete. Avoid steps with unclear objectives, like "
        "'Analyze the retrieved issues data,' where it's unclear what specific content"
        " needs to be analyzed.",
        "Please ensure that only the intelligent agents mentioned above are used, and"
        " you may use only the necessary parts of them. Allocate them to appropriate "
        "steps strictly based on their described capabilities and limitations. Each "
        "intelligent agent can be reused.",
        "Utilize the provided resources to assist in generating the plan steps "
        "according to the actual needs of the user's goals. Do not use unnecessary "
        "resources.",
        "Each step should ideally use only one type of resource to accomplish a "
        "sub-goal. If the current goal can be broken down into multiple subtasks of the"
        " same type, you can create mutually independent parallel tasks.",
        "Data resources can be loaded and utilized by the appropriate intelligent "
        "agents without the need to consider the issues related to data loading links.",
        "Try to merge continuous steps that have sequential dependencies. If the "
        "user's goal does not require splitting, you can create a single-step task with"
        " content that is the user's goal.",
        "Carefully review the plan to ensure it comprehensively covers all information"
        " involved in the user's problem and can ultimately achieve the goal. Confirm"
        " whether each step includes the necessary resource information, such as URLs,"
        " resource names, etc.",
    ]
    desc_zh: str = "你是一个任务规划专家！可以协调智能体，分配资源完成复杂的任务目标。"
    desc: str = (
        "You are a task planning expert! You can coordinate intelligent agents"
        " and allocate resources to achieve complex task goals."
    )

    examples: str = """
    user:help me build a sales report summarizing our key metrics and trends
    assistants:[
        {{
            "serial_number": "1",
            "agent": "DataScientist",
            "content": "Retrieve total sales, average sales, and number of transactions grouped by "product_category"'.",
            "rely": ""
        }},
        {{
            "serial_number": "2",
            "agent": "DataScientist",
            "content": "Retrieve monthly sales and transaction number trends.",
            "rely": ""
        }},
        {{
            "serial_number": "3",
            "agent": "Reporter",
            "content": "Integrate analytical data into the format required to build sales reports.",
            "rely": "1,2"
        }}
    ]
    """  # noqa: E501

    def __init__(self, **kwargs):
        """Create a new PlannerAgent instance."""
        super().__init__(**kwargs)
        self._init_actions([PlanAction])

    def _init_reply_message(self, received_message: AgentMessage):
        reply_message = super()._init_reply_message(received_message)
        reply_message.context = {
            "agents": "\n".join(
                [f"- {item.profile}:{item.desc}" for item in self.agents]
            ),
        }
        return reply_message

    def bind_agents(self, agents: List[ConversableAgent]) -> ConversableAgent:
        """Bind the agents to the planner agent."""
        self.agents = agents
        for agent in self.agents:
            if agent.resources and len(agent.resources) > 0:
                self.resources.extend(agent.resources)
        return self

    def prepare_act_param(self) -> Dict[str, Any]:
        """Prepare the parameters for the act method."""
        return {
            "context": self.not_null_agent_context,
            "plans_memory": self.memory.plans_memory,
        }
