package main

import (
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"time"
)

var allowedTaskTypes = map[string]bool{
	"wechat_reply":   true,
	"wechat_observe": true,
	"noop":           true,
}

var allowedActionTypes = map[string]bool{
	"click":         true,
	"type_text":     true,
	"press_enter":   true,
	"observe_again": true,
	"scroll":        true,
	"wait":          true,
	"noop":          true,
}

func finalizeTask(task Task, summaries []RegionSummary, config Config, regionsPath string, screenshotPath string) Task {
	now := time.Now()
	if task.TaskID == "" {
		task.TaskID = "task_" + now.Format("20060102_150405")
	}
	if task.TaskName == "" {
		task.TaskName = "识别微信聊天并生成回复"
	}
	if task.TaskType == "" || !allowedTaskTypes[task.TaskType] {
		task.TaskType = "wechat_reply"
	}
	if task.TaskStatus == "" {
		task.TaskStatus = "planned"
	}
	if config.Agent.DryRun {
		task.TaskStatus = "dry_run"
	}
	if task.CreatedAt == "" {
		task.CreatedAt = now.Format(time.RFC3339)
	}
	task.Source = TaskSource{RegionsPath: regionsPath, ScreenshotPath: screenshotPath}
	task.Regions = summaries

	regionIndex := regionByType(summaries)
	if len(task.Actions) == 0 {
		task.Actions = defaultActions(task.LLMSummary.ReplyText)
	}

	for index := range task.Actions {
		action := &task.Actions[index]
		if action.ActionID == "" {
			action.ActionID = fmt.Sprintf("action_%03d", index+1)
		}
		if action.Name == "" {
			action.Name = action.Type
		}
		if !allowedActionTypes[action.Type] {
			action.Type = "noop"
			action.Reason = "unsupported action type replaced by noop"
		}
		if action.Type == "click" || action.Type == "scroll" {
			if summary, exists := regionIndex[action.TargetRegion]; exists {
				point := summary.CenterScreen
				action.Point = &point
			} else if action.Type == "click" || action.Type == "scroll" {
				action.Type = "noop"
				action.Reason = "target_region not found"
			}
		}
		if action.Type == "scroll" {
			if action.TargetRegion != "chat_content" {
				action.Type = "noop"
				action.Reason = "scroll only allowed on chat_content"
			}
			if action.DeltaY > 5 {
				action.DeltaY = 5
			}
			if action.DeltaY < -5 {
				action.DeltaY = -5
			}
			if action.DeltaY == 0 {
				action.DeltaY = -3
			}
		}
		if action.Type == "type_text" && len([]rune(action.Text)) > 500 {
			runes := []rune(action.Text)
			action.Text = string(runes[:500])
		}
		if config.Agent.DryRun {
			action.Status = "skipped"
			if action.Reason == "" {
				action.Reason = "dry_run enabled"
			}
		} else if action.Status == "" {
			action.Status = "pending"
		}

		task.ExecutionLog = append(task.ExecutionLog, ExecutionLog{
			ActionID: action.ActionID,
			Status:   action.Status,
			Message:  executionMessage(*action),
			Time:     time.Now().Format(time.RFC3339),
		})
	}

	return task
}

func defaultActions(replyText string) []Action {
	if strings.TrimSpace(replyText) == "" {
		return []Action{{ActionID: "action_001", Type: "noop", Name: "无需回复", Status: "pending"}}
	}

	return []Action{
		{ActionID: "action_001", Type: "click", Name: "点击输入框", Status: "pending", TargetRegion: "input_box"},
		{ActionID: "action_002", Type: "type_text", Name: "输入回复内容", Status: "pending", Text: replyText},
		{ActionID: "action_003", Type: "press_enter", Name: "按回车发送", Status: "pending"},
	}
}

func executionMessage(action Action) string {
	switch action.Type {
	case "click":
		return fmt.Sprintf("dry_run: 跳过点击 %s", action.TargetRegion)
	case "type_text":
		return "dry_run: 跳过输入回复内容"
	case "press_enter":
		return "dry_run: 跳过按回车发送"
	case "scroll":
		return fmt.Sprintf("dry_run: 跳过滑动 %s delta_y=%d", action.TargetRegion, action.DeltaY)
	case "observe_again":
		return "dry_run: 跳过重新截图并识别"
	case "wait":
		return fmt.Sprintf("dry_run: 跳过等待 %dms", action.DurationMs)
	default:
		return "dry_run: noop"
	}
}

func saveTaskFiles(task Task, config Config) (string, string, error) {
	latestPath := appDataPath(config, config.Agent.TaskOutputPath)
	historyDir := appDataPath(config, config.Agent.TaskHistoryDir)
	if err := os.MkdirAll(filepath.Dir(latestPath), 0755); err != nil {
		return "", "", err
	}
	if err := os.MkdirAll(historyDir, 0755); err != nil {
		return "", "", err
	}

	data, err := json.MarshalIndent(task, "", "  ")
	if err != nil {
		return "", "", err
	}

	if err := os.WriteFile(latestPath, data, 0644); err != nil {
		return "", "", err
	}

	historyPath := filepath.Join(historyDir, task.TaskID+".json")
	if err := os.WriteFile(historyPath, data, 0644); err != nil {
		return "", "", err
	}

	return latestPath, historyPath, nil
}

func saveRawResponse(config Config, raw string) error {
	path := appDataPath(config, "data/tasks/latest_task_raw.txt")
	if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
		return err
	}
	return os.WriteFile(path, []byte(raw), 0644)
}
