package weixinapi

import (
	"git.rosy.net.cn/baseapi/utils"
)

const (
	MaxRemarkByteCount = 30

	ticketType = "wx_card"
	authType   = 0 //Int	是	授权类型，0：开票授权，1：填写字段开票授权，2：领票授权
	//图片（image）、视频（video）、语音 （voice）、图文（news）
	MaterialTypeImage = "image"
	MaterialTypeVideo = "video"
	MaterialTypeVoice = "voice"
	MaterialTypeNews  = "news"
	MaterialTypeThumb = "thumb"

	SNSCutLine = `
	<br>
	<hr style=\"border-style: solid;border-width: 1px 0 0;border-color: rgba(0,0,0,0.1);-webkit-transform-origin: 0 0;-webkit-transform: scale(1, 0.5);transform-origin: 0 0;transform: scale(1, 0.5);\"  />
	<br>
	`
)

type CBUserInfo struct {
	Subscribe      int    `json:"subscribe"`
	OpenID         string `json:"openid"`
	Nickname       string `json:"nickname"`
	Sex            int    `json:"sex"`
	Language       string `json:"language"`
	City           string `json:"city"`
	Province       string `json:"province"`
	Country        string `json:"country"`
	HeadImgURL     string `json:"headimgurl"`
	SubscribeTime  int64  `json:"subscribe_time"`
	UnionID        string `json:"unionid"`
	Remark         string `json:"remark"`
	TagIDList      []int  `json:"tagid_list"`
	SubscribeScene string `json:"subscribe_scene"`
	QRScene        int    `json:"qr_scene"`
	QRSceneStr     string `json:"qr_scene_str"`
}

type CBTicketInfo struct {
	Errcode   int    `json:"errcode"`
	Errmsg    string `json:"errmsg"`
	Ticket    string `json:"ticket"`
	ExpiresIn int    `json:"expires_in"`
}

func (a *API) CBSetToken(newToken string) bool {
	curToken := a.CBGetToken()
	if curToken != newToken {
		a.locker.Lock()
		defer a.locker.Unlock()
		a.token = newToken
		return true
	}
	return false
}

func (a *API) CBGetToken() string {
	a.locker.RLock()
	defer a.locker.RUnlock()
	return a.token
}

func (a *API) CBRetrieveToken() (tokenInfo *TokenInfo, err error) {
	result, err := a.AccessAPI("cgi-bin/token", utils.Params2Map("grant_type", "client_credential"), "")
	if err != nil {
		return nil, err
	}
	tokenInfo = &TokenInfo{
		AccessToken: utils.Interface2String(result["access_token"]),
		ExpiresIn:   int(utils.MustInterface2Int64(result["expires_in"])),
	}
	a.CBSetToken(tokenInfo.AccessToken)
	return tokenInfo, nil
}

func (a *API) CBMessageTemplateSend(userOpenID, templateID, downloadURL string, miniProgram, data interface{}) (err error) {
	bodyJson := map[string]interface{}{
		"touser":      userOpenID,
		"template_id": templateID,
		"url":         downloadURL,
		"data":        data,
	}
	if downloadURL != "" {
		bodyJson["url"] = downloadURL
	}
	if miniProgram != nil {
		bodyJson["miniprogram"] = miniProgram
	}

	_, err = a.AccessAPI("cgi-bin/message/template/send", nil, string(utils.MustMarshal(bodyJson)))
	return err
}

// remark的字节数不超过30个字节
func (a *API) CBUpdateRemark(userOpenID, remark string) (err error) {
	bodyJson := map[string]interface{}{
		"openid": userOpenID,
		"remark": utils.LimitMixedStringLen(remark, MaxRemarkByteCount),
	}
	_, err = a.AccessAPI("cgi-bin/user/info/updateremark", nil, string(utils.MustMarshal(bodyJson)))
	return err
}

func (a *API) CBGetUserInfo(userOpenID string) (userInfo *CBUserInfo, err error) {
	bodyJson := map[string]interface{}{
		"openid": userOpenID,
		"lang":   "zh_CN",
	}
	result, err := a.AccessAPI("cgi-bin/user/info", bodyJson, "")
	if err == nil {
		err = utils.Map2StructByJson(result, &userInfo, false)
	}
	return userInfo, err
}

//获取授权页ticket
func (a *API) CBGetTicketInfo() (ticketInfo *CBTicketInfo, err error) {
	bodyJson := map[string]interface{}{
		"type": ticketType,
	}
	result, err := a.AccessAPI("cgi-bin/ticket/getticket", bodyJson, "")
	if err == nil {
		err = utils.Map2StructByJson(result, &ticketInfo, false)
	}
	return ticketInfo, err
}

type CBBatchgetMaterialResult struct {
	Item []struct {
		MediaID string `json:"media_id"`
		Content struct {
			NewsItem []struct {
				Title              string `json:"title"`
				Author             string `json:"author"`
				Digest             string `json:"digest"`
				Content            string `json:"content"`
				ContentSourceURL   string `json:"content_source_url"`
				ThumbMediaID       string `json:"thumb_media_id"`
				ShowCoverPic       int    `json:"show_cover_pic"`
				URL                string `json:"url"`
				ThumbURL           string `json:"thumb_url"`
				NeedOpenComment    int    `json:"need_open_comment"`
				OnlyFansCanComment int    `json:"only_fans_can_comment"`
			} `json:"news_item"`
			CreateTime int `json:"create_time"`
			UpdateTime int `json:"update_time"`
		} `json:"content"`
		UpdateTime int `json:"update_time"`
	} `json:"item"`
	TotalCount int `json:"total_count"`
	ItemCount  int `json:"item_count"`
}

//获取素材列表
func (a *API) CBBatchgetMaterial(mediaType string, offset, count int) (ticketInfo *CBBatchgetMaterialResult, err error) {
	bodyJson := map[string]interface{}{
		"type":   mediaType,
		"offset": offset,
		"count":  count,
	}
	result, err := a.AccessAPI("cgi-bin/material/batchget_material", nil, string(utils.MustMarshal(bodyJson)))
	if err == nil {
		err = utils.Map2StructByJson(result, &ticketInfo, false)
	}
	return ticketInfo, err
}

//上传图片
func (a *API) CBUploadImg(data []byte, fileName, contentType string) (url string, err error) {
	result, err := a.AccessAPIUpload("cgi-bin/media/uploadimg", data, fileName, contentType, "")
	if err == nil {
		return result["url"].(string), err
	}
	return url, err
}

//上传图片素材
func (a *API) CBUploadThumb(data []byte, fileName, contentType string) (mediaID, url string, err error) {
	result, err := a.AccessAPIUpload("cgi-bin/material/add_material", data, fileName, contentType, MaterialTypeThumb)
	if err == nil {
		return result["media_id"].(string), result["url"].(string), err
	}
	return mediaID, url, err
}

type CBAddNewsParamF struct {
	Articles []*CBAddNewsParam `json:"articles"`
}

type CBAddNewsParam struct {
	Title              string `json:"title"`                 //是	标题
	ThumbMediaID       string `json:"thumb_media_id"`        //是	图文消息的封面图片素材id（必须是永久mediaID）
	Author             string `json:"author"`                //否	作者
	Digest             string `json:"digest"`                //否	图文消息的摘要，仅有单图文消息才有摘要，多图文此处为空。如果本字段为没有填写，则默认抓取正文前54个字。
	ShowCoverPic       int    `json:"show_cover_pic"`        //是	是否显示封面，0为false，即不显示，1为true，即显示
	Content            string `json:"content"`               //是	图文消息的具体内容，支持HTML标签，必须少于2万字符，小于1M，且此处会去除JS,涉及图片url必须来源 "上传图文消息内的图片获取URL"接口获取。外部图片url将被过滤。
	ContentSourceUrl   string `json:"content_source_url"`    //是	图文消息的原文地址，即点击“阅读原文”后的URL
	NeedOpenComment    int    `json:"need_open_comment"`     //否	Uint32 是否打开评论，0不打开，1打开
	OnlyFansCanComment int    `json:"only_fans_can_comment"` //否	Uint32 是否粉丝才可评论，0所有人可评论，1粉丝才可评论
}

//新增永久图文素材
func (a *API) CBAddNews(cbAddNewsParam *CBAddNewsParam) (mediaID string, err error) {
	params := &CBAddNewsParamF{
		Articles: []*CBAddNewsParam{},
	}
	params.Articles = append(params.Articles, cbAddNewsParam)
	bodyJson := utils.Struct2FlatMap(params)
	result, err := a.AccessAPI("cgi-bin/material/add_news", nil, string(utils.MustMarshal(bodyJson)))
	if err == nil {
		return result["media_id"].(string), err
	}
	return mediaID, err
}

//根据OpenID列表群发【订阅号不可用，服务号认证后可用】
func (a *API) CBMassSend(openIDs []string, mediaID string) (err error) {
	bodyJson := map[string]interface{}{
		"touser": openIDs,
		"mpnews": map[string]interface{}{
			"media_id": mediaID,
		},
		"msgtype": "mpnews",
	}
	_, err = a.AccessAPI("cgi-bin/message/mass/send", nil, string(utils.MustMarshal(bodyJson)))
	return err
}
