// Agent-based plan generation (tool-calling loop)

import { searchPois, getTransitDirection } from "@/lib/amap";
import { runAgentLoop, type AgentTool } from "@/lib/ai";
import type { TaggedIdea } from "./ideaSelection";
import type { PlanGenAvailableTime } from "./index";

export const AGENT_SYSTEM_PROMPT = `你是一个周末行程规划 Agent。你有以下工具可以使用：
- list_ideas: 查看想法池中的所有活动
- search_poi: 在地图上搜索地点（支持品牌名、地名、品类搜索）
- get_travel_time: 查询两点间公共交通（地铁/公交）时间和距离
- finalize_plan: 提交最终行程方案

规划流程：
1. 先用 list_ideas 了解有哪些活动可选
2. 根据时间、多样性、强度平衡选出合适的活动组合
3. 为每个活动 search_poi 找到具体地点
4. 如果搜索结果不理想（0结果或不相关），尝试换关键词重搜
5. 用 get_travel_time 检查关键路段，如果某段超过 45 分钟考虑换更近的地点
6. 确认地点合理后 finalize_plan 提交

规划原则：
- 地理位置相近，最小化移动距离
- 严格遵守用餐时间窗口：午餐安排在 11:30-13:00，晚餐安排在 17:30-19:30，不得超出此范围
- 尊重时间偏好（morning 的活动放 9:00-12:00，afternoon 的活动放 13:00-17:00，evening 的活动放 19:00 以后）
- 活动间留 15-30 分钟交通时间
- 高低强度交替，避免连续高体力活动
- 费用均衡，不连续安排 premium 活动
- needsBooking 的活动在 reason 中提醒预约

每次调用工具前，用一句简短的话说明你的想法（用户能看到）。`;

export interface FinalizePlanDay {
  date: string;
  items: {
    time: string;
    activity: string;
    poi: string;
    address: string;
    lat: number;
    lng: number;
    duration: number;
    reason: string;
  }[];
  summary: string;
}

export function buildAgentTools(
  taggedIdeas: TaggedIdea[],
  lat: number,
  lng: number,
  city: string,
): AgentTool[] {
  const listIdeasTool: AgentTool = {
    name: "list_ideas",
    description: "获取想法池中所有已标记的活动想法，包含品类、时间偏好、费用、强度等信息",
    parameters: {
      type: "object",
      properties: {},
      required: [],
    },
    execute: async () => {
      const ideas = taggedIdeas.map((i) => ({
        id: i.id,
        content: i.content,
        category: i.category,
        timeSlot: i.timeSlot,
        estimatedMinutes: i.estimatedMinutes,
        costLevel: i.costLevel,
        intensity: i.intensity,
        needsBooking: i.needsBooking,
      }));
      return JSON.stringify(ideas);
    },
    progressBefore: () => "正在查看想法池...",
    progressAfter: (_args, result) => {
      const ideas = JSON.parse(result);
      return `找到 ${ideas.length} 个想法`;
    },
  };

  const searchPoiTool: AgentTool = {
    name: "search_poi",
    description: "在地图上搜索地点。search_type: brand=连锁品牌, place=唯一地点, category=模糊品类搜附近",
    parameters: {
      type: "object",
      properties: {
        query: { type: "string", description: "搜索关键词（品牌名、地名或品类名）" },
        search_type: {
          type: "string",
          enum: ["brand", "place", "category"],
          description: "搜索策略",
        },
      },
      required: ["query", "search_type"],
    },
    execute: async (args) => {
      const query = String(args.query ?? "");
      const searchType = String(args.search_type ?? "category");
      try {
        const pois = await searchPois(query, searchType, lat, lng);
        return JSON.stringify(pois);
      } catch (e) {
        console.error("searchPoiTool failed:", e);
        return JSON.stringify([]);
      }
    },
    progressBefore: (args) => `正在搜索「${args.query}」...`,
    progressAfter: (args, result) => {
      const pois = JSON.parse(result);
      return pois.length > 0
        ? `找到 ${pois.length} 个「${args.query}」相关地点`
        : `未找到「${args.query}」的结果`;
    },
  };

  const getTravelTimeTool: AgentTool = {
    name: "get_travel_time",
    description: "查询两点之间的公共交通（地铁/公交）预估时间和距离。用于验证活动之间的交通是否合理",
    parameters: {
      type: "object",
      properties: {
        origin_lat: { type: "number", description: "起点纬度" },
        origin_lng: { type: "number", description: "起点经度" },
        dest_lat: { type: "number", description: "终点纬度" },
        dest_lng: { type: "number", description: "终点经度" },
      },
      required: ["origin_lat", "origin_lng", "dest_lat", "dest_lng"],
    },
    execute: async (args) => {
      try {
        const result = await getTransitDirection({
          originLat: Number(args.origin_lat),
          originLng: Number(args.origin_lng),
          destLat: Number(args.dest_lat),
          destLng: Number(args.dest_lng),
          city,
        });
        if (!result) return JSON.stringify({ error: "未找到公交路线" });
        return JSON.stringify(result);
      } catch (e) {
        console.error("getTravelTimeTool failed:", e);
        return JSON.stringify({ error: "路线查询失败" });
      }
    },
    progressBefore: () => "正在查询公共交通时间...",
    progressAfter: (_args, result) => {
      const r = JSON.parse(result);
      if (r.error) return `路线查询失败`;
      return `${r.description} 约 ${r.durationMin} 分钟（${r.distanceKm}km）`;
    },
  };

  const finalizePlanTool: AgentTool = {
    name: "finalize_plan",
    description: "提交最终行程方案。days 数组中每个元素包含 date、items（活动列表）和 summary",
    parameters: {
      type: "object",
      properties: {
        days: {
          type: "array",
          items: {
            type: "object",
            properties: {
              date: { type: "string" },
              items: {
                type: "array",
                items: {
                  type: "object",
                  properties: {
                    time: { type: "string", description: "开始时间，如 10:00" },
                    activity: { type: "string", description: "活动描述" },
                    poi: { type: "string", description: "具体地点名称" },
                    address: { type: "string", description: "详细地址" },
                    lat: { type: "number" },
                    lng: { type: "number" },
                    duration: { type: "number", description: "时长（分钟）" },
                    reason: { type: "string", description: "选择理由" },
                  },
                  required: ["time", "activity", "poi", "address", "lat", "lng", "duration", "reason"],
                },
              },
              summary: { type: "string", description: "当天行程亮点一句话总结" },
            },
            required: ["date", "items", "summary"],
          },
        },
      },
      required: ["days"],
    },
    execute: async () => {
      return JSON.stringify({ success: true });
    },
    progressBefore: () => "正在整理最终行程...",
    progressAfter: () => "行程规划完成！",
  };

  return [listIdeasTool, searchPoiTool, getTravelTimeTool, finalizePlanTool];
}

export async function runAgentPlanGeneration(
  room: { lat: number; lng: number; city: string },
  taggedIdeas: TaggedIdea[],
  availableTime: PlanGenAvailableTime,
  onProgress?: (message: string) => void,
): Promise<{ days: FinalizePlanDay[] }> {
  const at = availableTime;
  const tools = buildAgentTools(taggedIdeas, room.lat, room.lng, room.city ?? "");

  const userPrompt = `帮我规划行程。
可用时间：${at.date}，${at.startHour}:00 - ${at.endHour}:00
出发地（家）：纬度 ${room.lat}，经度 ${room.lng}
注意：第一个活动需要从出发地出发，最后一个活动结束后需要返回出发地，请用 get_travel_time 评估出发/回程时间并计入全天时间预算（确保最后一个活动结束时间 + 回程时间 ≤ ${at.endHour}:00）。
请开始规划。`;

  const result = await runAgentLoop({
    systemPrompt: AGENT_SYSTEM_PROMPT,
    userPrompt,
    tools,
    onProgress,
    maxTurns: 15,
  });

  if (!result) {
    throw new Error("Agent 未能在限定轮次内完成规划");
  }

  const days = result.finalArgs.days as FinalizePlanDay[] | undefined;
  if (!Array.isArray(days) || days.length === 0) {
    throw new Error("Agent 返回的行程数据无效");
  }

  const normalizedDays = days.map((day) => ({
    date: String(day.date ?? ""),
    items: Array.isArray(day.items)
      ? day.items.map((item) => ({
          time: String(item.time ?? ""),
          activity: String(item.activity ?? ""),
          poi: String(item.poi ?? ""),
          address: String(item.address ?? ""),
          lat: Number(item.lat) || 0,
          lng: Number(item.lng) || 0,
          duration: Number(item.duration) || 60,
          reason: String(item.reason ?? ""),
        }))
      : [],
    summary: String(day.summary ?? ""),
  }));

  const validDays = normalizedDays.filter((d) => d.items.length > 0);
  if (validDays.length === 0) {
    throw new Error("Agent 返回的行程中没有有效活动");
  }

  return { days: validDays };
}
