from .state import TravelState
from .tools import get_transport_tools,get_hotel_tools,get_attraction_tools
from langchain.agents import create_agent
from llm import create_model
from config import load_config


config=load_config()
llm = create_model(config)

def coordinator_node(state: TravelState)->dict:
    return{}
#路线agent节点
async def transport_agent_node(state: TravelState) -> dict:

    user_request= state["user_request"]
    tools=await get_transport_tools()
    agent = create_agent(
        model=llm,
        tools=tools,
        system_prompt="""你是旅行规划系统中的交通专家，只负责交通与市内通勤建议。
根据用户需求，必要时调用地图工具查询路线、距离或交通方式。
优先提供公共交通建议；用户明确自驾时再提供驾车建议。
若用户未提供出发地、日期等关键条件，应明确说明你的假设或待确认信息。
不得推荐酒店、景点或编造工具未返回的路线数据。
输出应包含：推荐交通方式、预计耗时、关键换乘/路线信息、出行提醒。"""
    )
    result = await agent.ainvoke({"messages":[{"role":"user","content":user_request}]})
    return {"transport_plan":result["messages"][-1].content}

#酒店agent节点
async def hotel_agent_node(state:TravelState)->dict:

    user_request= state["user_request"]
    tools=await get_hotel_tools()
    agent = create_agent(
            model=llm,
            tools=tools,
            system_prompt="""你是旅行规划系统中的住宿专家，只负责查询与推荐住宿。

当用户给出了目的地时，必要时调用 hotel_search_and_recommend。
调用时：
- destination 必填，从用户请求中提取城市、区域或地标；
- query 传入完整用户原始需求；
- scene 可映射为商务、亲子、度假、背包或通用；
- 用户明确给出入住/退房日期时，才传 YYYY-MM-DD 格式的 check_in/check_out；
- guests 取用户明确人数，未说明时可省略；
- max_price 只在用户明确给出“每晚预算”时传入；总旅行预算不能直接当作每晚预算。

如果用户没有目的地，不调用工具，并要求补充目的地。
不得编造酒店名称、价格、位置、评分或是否有房。
推荐结果不代表已完成预订。
不得规划交通、景点或完整行程。

输出格式：
1. 推荐住宿
2. 每晚价格与位置
3. 适合原因
4. 需用户确认的信息"""
        )
    result = await agent.ainvoke({"messages":[{"role":"user","content":user_request}]})
    return {"hotel_plan":result["messages"][-1].content}

#景点agent节点
async def attraction_agent_node(state:TravelState)->dict:

    user_request= state["user_request"]
    tools=await get_attraction_tools()
    agent = create_agent(
                model=llm,
                tools=tools,
                system_prompt="""你是旅行规划系统中的景点与活动专家，只负责景点推荐和游玩建议。
用户提供目的地时，必须调用地图工具查询景点或天气后再回答。
优先使用关键词搜索查找与用户偏好匹配的 POI。
需要了解特定地点时，使用详情搜索；需要查询某个地点周边内容时，先获得其坐标，再使用周边搜索。
根据天气工具结果给出合理出行提醒。

不得虚构景点地址、营业时间、门票、评分、距离或天气数据。
不得推荐酒店、规划交通路线或声称已完成预约。

输出应包含：
1. 推荐景点或区域；
2. 每个推荐的类型、位置或商圈信息；
3. 适合用户偏好的原因；
4. 天气与游玩提醒；
5. 需要用户确认的信息。"""
            )
    result = await agent.ainvoke({"messages":[{"role":"user","content":user_request}]})
    return {"attraction_plan":result["messages"][-1].content}

#整合agent
async def integrator_agent_node(state: TravelState) -> dict:

    user_request= state["user_request"]
    transport_plan=state.get("transport_plan")
    hotel_plan=state.get("hotel_plan")
    attraction_plan=state.get("attraction_plan")
    agent = create_agent(
                    model=llm,
                    tools=[],
                    system_prompt="""你是旅行规划系统中的方案整合专家。
只能依据用户需求及交通、住宿、景点专家提供的结果生成方案。
不得自行调用工具、补充未经专家结果支持的酒店、路线、景点价格、天气或营业信息。
若专家结果冲突、缺失或信息不足，明确标记“待确认”，不要编造。

输出格式：
1. 旅行概览
2. 交通与市内通勤
3. 住宿建议
4. 每日行程建议
5. 注意事项与待确认事项"""
                )
    compose_text=f"""【用户需求】{user_request}
    【交通专家结果】
    {transport_plan}
    【住宿专家结果】
    {hotel_plan}
    【景点专家结果】
    {attraction_plan}
    """
    result=await agent.ainvoke({"messages":[{"role":"user","content":compose_text}]})
    return {"final_plan":result["messages"][-1].content}