package main

import (
	"encoding/json"
	"errors"
	"strings"
)

func buildPrompt(summaries []RegionSummary) (string, error) {
	regionsJSON, err := json.MarshalIndent(summaries, "", "  ")
	if err != nil {
		return "", err
	}

	return `你是微信 RPA 多模态任务规划器。

请根据图片和标注区域完成：
1. 识别当前聊天记录。
2. 识别联系人或会话对象，如果无法识别则填 unknown。
3. 判断是否需要回复。
4. 如果需要回复，生成 reply_text。
5. 如果聊天上下文不足以判断是否回复，可以规划滚动聊天区域查看更多记录。
6. 生成 dry-run 动作计划。

限制：
- 只能返回合法 JSON，不要 Markdown，不要解释。
- 不要编造坐标。
- 点击坐标只能使用我提供的区域中心点。
- 如果区域 type 是 custom，请重点参考 description 判断该区域的用途和可执行动作。
- description 是用户标注时填写的用途说明，优先级高于模型自行猜测。
- 微信发送消息使用键入回车键，不要规划点击发送按钮。
- 如果当前聊天内容不足以判断是否回复，可以返回 scroll 动作。
- scroll 只能作用于 chat_content 区域。
- delta_y < 0 表示向上滚动查看更多历史消息；delta_y > 0 表示向下滚动回到最新消息。
- 每次最多返回一个 scroll 动作，abs(delta_y) 不要超过 5。
- 如果滚动后需要重新识别，请追加 observe_again 动作。
- 不要在同一个任务里同时包含 scroll 和 type_text/press_enter；上下文不足时先滚动观察，不要直接回复。
- action.type 只能是 click、type_text、press_enter、scroll、observe_again、wait、noop。
- 当前是 dry_run，只生成计划，不要假设动作已执行。
- 如果无需回复，task_type 使用 wechat_observe 或 noop，并给出 observations。

标注区域如下：
` + string(regionsJSON) + `

请严格返回如下 JSON 结构：
{
  "task_id": "",
  "task_name": "识别微信聊天并生成回复",
  "task_type": "wechat_reply",
  "task_status": "planned",
  "confidence": 0.0,
  "llm_summary": {
    "contact_name": "unknown",
    "chat_summary": "",
    "latest_user_message": "",
    "reply_text": ""
  },
  "actions": [
    {"action_id":"action_001","type":"click","name":"点击输入框","status":"pending","target_region":"input_box"},
    {"action_id":"action_002","type":"type_text","name":"输入回复内容","status":"pending","text":""},
    {"action_id":"action_003","type":"press_enter","name":"按回车发送","status":"pending"}
  ]
}`, nil
}

func extractJSON(text string) (string, error) {
	trimmed := strings.TrimSpace(text)
	trimmed = strings.TrimPrefix(trimmed, "```json")
	trimmed = strings.TrimPrefix(trimmed, "```")
	trimmed = strings.TrimSuffix(trimmed, "```")
	trimmed = strings.TrimSpace(trimmed)

	start := strings.Index(trimmed, "{")
	end := strings.LastIndex(trimmed, "}")
	if start < 0 || end < start {
		return "", errors.New("no JSON object found in LLM response")
	}

	return trimmed[start : end+1], nil
}

func parseTaskFromLLM(raw string) (Task, string, error) {
	jsonText, err := extractJSON(raw)
	if err != nil {
		return Task{}, "", err
	}

	var task Task
	if err := json.Unmarshal([]byte(jsonText), &task); err != nil {
		return Task{}, jsonText, err
	}

	return task, jsonText, nil
}
