package services

import (
	"bytes"
	"encoding/json"
	"errors"
	"eta/eta_mini_crm_ht/models"
	"eta/eta_mini_crm_ht/utils"
	"fmt"
	"io"
	"net/http"
	"time"
)

var (
	TemplateMsgSendUrl       = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%s"
	TemplateMsgClearQuotaUrl = "https://api.weixin.qq.com/cgi-bin/clear_quota?access_token=%s"
)

type TemplateMsgSendClient struct {
	AccessToken string
	Data        []byte
}

type SendTemplateResponse struct {
	Errcode int    `json:"errcode"`
	Errmsg  string `json:"errmsg"`
	MsgID   int    `json:"msgid"`
}

type ClearQuotaResponse struct {
	Errcode int    `json:"errcode"`
	Errmsg  string `json:"errmsg"`
}

type OpenIdList struct {
	OpenId string
	UserId int
}

// TemplateMsgSendClient.ClearQuota 清除发送超过当日10万次限制
func (c *TemplateMsgSendClient) ClearQuota() (result *ClearQuotaResponse, err error) {
	key := "CACHE_SendTemplateMsg_ERR"
	exists := utils.Rc.IsExist(key)
	if exists {
		return
	}
	_ = utils.Rc.SetEX(key, 1, 6*time.Minute)

	sendUrl := fmt.Sprintf(TemplateMsgClearQuotaUrl, c.AccessToken)
	client := http.Client{}
	clearData := make(map[string]interface{})
	clearData["appid"] = utils.HT_WX_APPID
	clearJson, _ := json.Marshal(clearData)
	resp, err := client.Post(sendUrl, "application/json", bytes.NewBuffer(clearJson))
	if err != nil {
		return
	}
	defer func() {
		_ = resp.Body.Close()
	}()
	clearBody, err := io.ReadAll(resp.Body)
	err = json.Unmarshal(clearBody, &result)
	return
}

// TemplateMsgSendClient.SendMsg 推送消息
func (c *TemplateMsgSendClient) SendMsg() (sendRes *SendTemplateResponse, err error) {
	// 请求接口
	sendUrl := fmt.Sprintf(TemplateMsgSendUrl, c.AccessToken)
	client := http.Client{}
	resp, err := client.Post(sendUrl, "application/json", bytes.NewBuffer(c.Data))
	if err != nil {
		return
	}
	defer func() {
		_ = resp.Body.Close()
	}()
	body, _ := io.ReadAll(resp.Body)
	if err = json.Unmarshal(body, &sendRes); err != nil {
		return
	}
	// 模板消息发送超过当日10万次限制错误处理
	if sendRes.Errcode == 45009 {
		// 发送提示邮件
		// go alarm_msg.SendAlarmMsg("模板消息发送超过当日10万次限制, SendTemplateResponse: "+string(body), 3)
		// 清理限制
		clearRes, e := c.ClearQuota()
		if e != nil {
			err = e
			return
		}
		if clearRes.Errcode != 0 {
			clearJson, er := json.Marshal(clearRes)
			if er != nil {
				return nil, er
			}
			fmt.Println("自动清理模板消息限制接口, 调用失败, ClearQuotaResponse: " + string(clearJson))
			// go alarm_msg.SendAlarmMsg("自动清理模板消息限制接口, 调用失败, ClearQuotaResponse: "+string(clearJson), 3)
			return
		}
		// 发送成功邮件
		// go alarm_msg.SendAlarmMsg("自动清理模板消息限制接口, 调用成功", 1)
		// 重新推送
		go func() {
			_, e := c.SendMsg()
			if e != nil {
				return
				// reSendJson, _ := json.Marshal(reSend)
				// alarm_msg.SendAlarmMsg("重新推送模板消息失败, SendTemplateResponse: "+string(reSendJson), 3)
			}
		}()
	}
	if sendRes.Errcode != 0 {
		err = errors.New("推送模板消息失败, SendTemplateResponse: " + string(body))
	}
	return
}

// AddUserTemplateRecord 新增模板消息推送记录
func AddUserTemplateRecord(userId, sendStatus int, sendType string, openid, sendData, result string) (err error) {
	item := &models.UserTemplateRecord{
		UserId:     userId,
		OpenId:     openid,
		SendData:   sendData,
		Result:     result,
		CreateDate: time.Now().Format(utils.FormatDate),
		CreateTime: time.Now().Format(utils.FormatDateTime),
		SendStatus: sendStatus,
		SendType:   sendType,
	}
	err = item.Insert()
	return
}

// SendMultiTemplateMsg 推送模板消息至多个用户
func SendMultiTemplateMsg(sendData map[string]interface{}, items []*OpenIdList, Id int, sendType string) (err error) {
	ws := GetWxChat()
	accessToken, err := ws.GetAccessToken()
	if err != nil {
		utils.FileLog.Info("获取微信token失败, Err:" + err.Error())
		// alarm_msg.SendAlarmMsg("获取微信token失败, Err:"+err.Error(), 1)
		return
	}
	sendMap := make(map[string]interface{})
	var path string
	switch sendType {
	case "report":
		path = "/pages-report/reportDetail/index?id=%d"
	case "audio":
		path = "/pages-media/audioDetail/index?id=%d"
	case "video":
		path = "/pages-media/videoDetail/index?id=%d"
	default:
		return errors.New("非法的消息类型")
	}
	for _, item := range items {
		sendMap["template_id"] = utils.TEMPLATE_ID_BY_PRODUCT
		sendMap["miniprogram"] = map[string]interface{}{
			"appid":    utils.HT_MINI_APPID,
			"pagepath": fmt.Sprintf(path, Id),
		}
		sendMap["touser"] = item.OpenId
		sendMap["data"] = sendData
		data, e := json.Marshal(sendMap)
		if e != nil {
			utils.FileLog.Info("新增模板消息推送记录失败, Err:" + e.Error())
			return
		}
		ts := &TemplateMsgSendClient{
			AccessToken: accessToken,
			Data:        data,
		}
		result, e := ts.SendMsg()
		if e != nil {
			utils.FileLog.Info("新增模板消息推送记录失败, Err:" + e.Error())
			return
		}
		if result == nil {
			return
		}
		// 推送消息记录
		{
			go func() {
				sendStatus := 1
				if e != nil {
					sendStatus = 0
				}
				resultJson, _ := json.Marshal(result)
				err = AddUserTemplateRecord(item.UserId, sendStatus, sendType, item.OpenId, string(data), string(resultJson))
				if err != nil {
					utils.FileLog.Info("新增模板消息推送记录失败, Err:" + err.Error())
					return
				}
			}()
		}
	}
	return
}
