package services

import (
	"encoding/json"
	"errors"
	"eta/eta_mini_crm_ht/models"
	"eta/eta_mini_crm_ht/utils"
	"fmt"
	"io"
	"net/http"
	"strings"
	"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
	FollowingGzh bool
}

//// 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(templateData SendWxTemplate, items []*OpenIdList, Id int, sendType string) (err error) {
	if err != nil {
		utils.FileLog.Info("获取微信token失败, Err:" + err.Error())
		return
	}
	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("非法的消息类型")
	}
	templateData.WxAppId = utils.HT_WX_APPID
	templateData.TemplateId = utils.TEMPLATE_ID_BY_PRODUCT
	templateData.RedirectUrl = fmt.Sprintf(path, Id)
	templateData.Resource = templateData.RedirectUrl
	templateData.SendType = 8
	for _, item := range items {
		templateData.OpenIdArr = append(templateData.OpenIdArr, item.OpenId)
	}
	templateData.RedirectTarget = 5
	return sendMsg(templateData)
}

type SendWxTemplate struct {
	WxAppId        string   `description:"公众号appId"`
	First          string   `description:"模板消息first字段"`
	Keyword1       string   `description:"模板消息keyword1字段"`
	Keyword2       string   `description:"模板消息keyword2字段"`
	Keyword3       string   `description:"模板消息keyword3字段"`
	Keyword4       string   `description:"模板消息keyword4字段"`
	Keyword5       string   `description:"模板消息keyword5字段"`
	Productname    string   `description:"模板消息productname字段"`
	Date           string   `description:"模板消息date字段"`
	Remark         string   `description:"模板消息remark字段"`
	TemplateId     string   `description:"模板id"`
	RedirectUrl    string   `description:"跳转地址"`
	RedirectTarget int      `description:"小程序跳转目标:1:弘则研报小程序,2:随手办公小程序,3:查研观向"`
	Resource       string   `description:"资源唯一标识"`
	SendType       int      `description:"发送的消息类型:1:报告,2:指标更新提醒,3:审批通知,4:销售领取客户通知,5:活动取消通知,6活动更改时间通知,7:关注的作者发布报告通知,8:发送日报（周报、双周报、月报）模板消息,9:活动预约/报名时间通知"`
	OpenIdArr      []string `description:"消息接收者openid"`
}

func sendMsg(template SendWxTemplate) (err error) {
	if utils.ETA_PUB_URL == `` {
		// 找不到推送服务
		return
	}
	// 设置请求 URL
	// 设置 POST 请求的数据
	data, err := json.Marshal(template)
	if err != nil {
		utils.FileLog.Error("发送消息模板失败，请求data json序列化失败，err:%v", err)
	}
	body := io.NopCloser(strings.NewReader(string(data)))
	req, _ := http.NewRequest("POST", utils.ETA_PUB_URL, body)
	if err != nil {
		fmt.Println("发送模板消息失败,创建请求失败:", err)
		return
	}
	// 设置 Content-Type
	req.Header.Set("Authorization", utils.ETA_PUB_TOKEN)
	req.Header.Set("Content-Type", "application/json;charset=utf-8")
	// 发送 POST 请求
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		utils.FileLog.Error("发送消息模板失败，请求失败，err:%v", err)
		return
	}
	defer resp.Body.Close()
	// 处理响应
	repBody, err := io.ReadAll(resp.Body)
	if err != nil {
		return err
	}
	if resp.StatusCode != http.StatusOK {
		utils.FileLog.Error("发送消息模板失败，请求失败，err:%v", string(repBody))
		return
	}
	utils.FileLog.Info("发送消息模板成功，请求成功，body:%v", string(repBody))
	return
}
