package youngee_talent_service

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"
	"youngmini_server/app/model/talent_model"

	"github.com/gogf/gf/encoding/gjson"
	"github.com/gogf/gf/frame/g"
	"github.com/gogf/gf/net/ghttp"
)

const (
	accessTokenUrlFormat = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s"
	qrCodeUrlFormat      = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=%s"
	wxAccesssTokenKey    = "wx_access_token"
)

// getAndCacheWxAccessToken 获取并缓存微信的access token
func getAndCacheWxAccessToken() (string, error) {
	appId := g.Config().GetString("miniapp.appid")
	secret := g.Config().GetString("miniapp.appsecret")
	url := fmt.Sprintf(accessTokenUrlFormat, appId, secret)

	resp, err := http.Get(url)
	if err != nil {
		return "", errors.New("request access token failed")
	}
	defer resp.Body.Close()

	// 解析微信服务端返回的信息
	var accessTokenRes talent_model.WxAccessTokenResponse
	decoder := json.NewDecoder(resp.Body)
	if err = decoder.Decode(&accessTokenRes); err != nil {
		return "", errors.New("decode wx response failed")
	}

	if accessTokenRes.Errcode != 0 {
		return "", errors.New("request access token failed")
	}

	// 缓存获取的access token,比微信返回的有效时间短5分钟失效
	_, err = g.Redis().Do("SETEX", wxAccesssTokenKey, accessTokenRes.ExpiresIn-300, accessTokenRes.AccessToken)

	return accessTokenRes.AccessToken, nil
}

func RequestShareInfo(r *ghttp.Request) *TalentHttpResult {

	var requestArg *talent_model.ShareRequest
	if err := r.ParseForm(&requestArg); err != nil {
		return &TalentHttpResult{Code: -1, Msg: "param error"}
	}

	// 获取access_token
	var accessToken string
	accessTokenVar, err := g.Redis().DoVar("GET", "wx_access_token")
	if err != nil {
		return &TalentHttpResult{Code: -2, Msg: "get access token from cache err"}
	}

	if accessTokenVar.IsEmpty() {
		// 如果没有缓存的access token 则获取并缓存
		accessToken, err = getAndCacheWxAccessToken()
	} else {
		// 取缓存的access token
		accessToken = accessTokenVar.String()
	}

	qrRequest := talent_model.WxQrCodeRequest{
		Scene:      requestArg.Scene,
		Page:       requestArg.Page,
		Width:      430,
		CheckPath:  false,
		EnvVersion: "release",
	}
	jsonBody, err := gjson.Encode(qrRequest)
	if err != nil {
		return &TalentHttpResult{Code: -3, Msg: ""}
	}

	qrCodeUrl := fmt.Sprintf(qrCodeUrlFormat, accessToken)
	resp, err := http.Post(qrCodeUrl, "application/json; charset=utf8", bytes.NewReader(jsonBody))
	if err != nil {
		return &TalentHttpResult{Code: -4, Msg: "request from wx server failed"}
	}
	defer resp.Body.Close()

	var qrcodeBytes []byte

	switch header := resp.Header.Get("content-Type"); {
	case strings.HasPrefix(header, "application/json"):
		// 如果返回的是json结构，说明发生错误
		var qrResponse *talent_model.WxQrCodeResponse
		decoder := json.NewDecoder(resp.Body)
		if err = decoder.Decode(&qrResponse); err != nil {
			return &TalentHttpResult{Code: -5, Msg: "request qrcode failed"}
		}

		return &TalentHttpResult{Code: -6, Msg: "wx request error", Data: qrResponse}
	case strings.HasPrefix(header, "image"):
		qrcodeBytes, err = ioutil.ReadAll(resp.Body)
		if err != nil {
			return &TalentHttpResult{Code: -6, Msg: "read resp body error"}
		}
	}

	return &TalentHttpResult{Code: 0, Msg: "success", Data: qrcodeBytes}
}
