package task

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"sundynix-go/global"
	"sundynix-go/model/plant"
	"sundynix-go/model/system"
	"sundynix-go/pkg/httpclient"
	"sundynix-go/utils/timer"
	"sundynix-go/utils/wechat"
	"time"
)

type TemplateDataItem struct {
	Value string `json:"value"`
}

// SendMessagePayload 是我们发送给微信服务器的消息体
type SendMessagePayload struct {
	TemplateID       string                      `json:"template_id"`
	Page             string                      `json:"page"`
	Touser           string                      `json:"touser"`
	Data             map[string]TemplateDataItem `json:"data"`
	MiniProgramState string                      `json:"miniprogram_state"` //跳转小程序类型：developer为开发版；trial为体验版；formal为正式版；默认为正式版
	Lang             string                      `json:"lang"`
}

// SendMessageResponse 是发送消息的响应体
type SendMessageResponse struct {
	Errcode int    `json:"errcode"`
	Errmsg  string `json:"errmsg"`
}

// SendCareMsg 发送提醒消息
func SendCareMsg() error {
	httpUrl := "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + wechat.GetMiniAccessToken()
	//1.查询出今日的养护任务
	now := time.Now()
	today := timer.GetZeroTime()
	endOfToday := today.Add(24 * time.Hour)
	var tasks []*plant.CareTask
	err := global.DB.Where("status = 1 and due_date < ?", endOfToday).Order("due_date ASC").Find(&tasks).Error
	if len(tasks) > 0 {
		// 将tasks分组，key为用户id 保证无论用户有多少植物，只给用户发送一条消息
		tasksMap := make(map[string][]*plant.CareTask)
		for _, task := range tasks {
			//用户id不为空再添加
			if task.UserId != "" {
				tasksMap[task.UserId] = append(tasksMap[task.UserId], task)
			}
		}
		for userId, cares := range tasksMap {
			//1.查询用户
			var user system.User
			err = global.DB.Where("id = ?", userId).First(&user).Error
			if err != nil {
				return err
			}
			if user.MiniOpenId != "" {
				//2.用户该养护的植物
				plantId := cares[0].PlantId
				var myPlant plant.MyPlant
				err = global.DB.Where("id = ?", plantId).First(&myPlant).Error
				if err != nil {
					return err
				}
				//3.构造请求参数 发送订阅消息
				payload := SendMessagePayload{
					TemplateID: "iG5GYMPQAgKxIE9zZNOgKS6tCURhM9p9AC8iZ3Uj3uA",
					Page:       "pages/tasks/index",
					Touser:     user.MiniOpenId,
					Data: map[string]TemplateDataItem{
						"thing1": {
							Value: myPlant.Name + "等",
						},
						"time3": {
							// 今天的九点
							Value: time.Date(now.Year(), now.Month(), now.Day(), 8, 30, 0, 0, time.Local).Format("2006-01-02"),
						},
					},
					MiniProgramState: "formal",
					//MiniProgramState: "trial",
					Lang: "zh_CN",
				}
				payloadBytes, err := json.Marshal(payload)
				if err != nil {
					return err
				}
				myHttpClient := httpclient.GetClient()
				resp, err := myHttpClient.Post(httpUrl, "application/json", bytes.NewBuffer(payloadBytes))
				if err != nil {
					return err
				}
				defer resp.Body.Close()
				body, err := io.ReadAll(resp.Body)
				if err != nil {
					return fmt.Errorf("读取订阅消息响应失败: %v", err)
				}

				var smr SendMessageResponse
				err = json.Unmarshal(body, &smr)
				if err != nil {
					return fmt.Errorf("解析订阅消息响应失败: %v, body: %s", err, string(body))
				}

				if smr.Errcode != 0 {
					global.Logger.Error(fmt.Sprintf("订阅消息发送失败! userId: %s, openId: %s, errcode: %d, errmsg: %s", userId, user.MiniOpenId, smr.Errcode, smr.Errmsg))
					continue // 不要因为某个用户失败（如43101没配额）而中断整个发送流程
				}
				global.Logger.Info(fmt.Sprintf("订阅消息发送成功! userId: %s, openId: %s", userId, user.MiniOpenId))
			}
		}
	}
	return nil
}
