package talent_service

import (
	"encoding/json"
	"fmt"
	"github.com/gogf/gf/crypto/gmd5"
	"github.com/gogf/gf/frame/g"
	"github.com/gogf/gf/net/ghttp"
	"github.com/gogf/gf/os/gtime"
	"net/http"
	"youngmini_server/app/dao"
	"youngmini_server/app/model/talent_model"
)

type WxLoginResult struct {
	OpenId     string `json:"openid"`
	SessionKey string `json:"session_key"`
	UnionId    string `json:"unionid"`
	ErrCode    int    `json:"errcode"`
	ErrMsg     string `json:"errmsg"`
}

const (
	urlformat = "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code"
)

func WxLogin(r *ghttp.Request) *TalentHttpResult {
	l := talent_model.WxLoginInfo{}
	err := r.ParseForm(&l)
	if err != nil {
		return &TalentHttpResult{Code: -1, Msg: "param error"}
	}

	//if e := gvalid.CheckStruct(context.TODO(), l, nil); e != nil {
	//	return &TalentHttpResult{Code: -2, Msg: "param invalid "}
	//}

	appId := g.Config().GetString("miniapp.appid")
	secret := g.Config().GetString("miniapp.appsecret")

	url := fmt.Sprintf(urlformat, appId, secret, l.Code)
	resp, err := http.Get(url)
	if err != nil {
		return &TalentHttpResult{Code: -2, Msg: err.Error()}
	}
	defer resp.Body.Close()

	// 解码微信服务端传来的信息
	wxResp := WxLoginResult{}
	decoder := json.NewDecoder(resp.Body)
	if err = decoder.Decode(&wxResp); err != nil {
		return &TalentHttpResult{Code: -3, Msg: "decode json from wx fail"}
	}

	if wxResp.ErrCode != 0 {
		return &TalentHttpResult{Code: -4, Msg: fmt.Sprintf("errCode:%d, errmsg:%s", wxResp.ErrCode, wxResp.ErrMsg)}
	}

	// 根据openid查询达人信息
	rec, err := g.DB().Model("talent_info").One("talent_wx_openid", wxResp.OpenId)
	if err != nil {
		return &TalentHttpResult{Code: -5, Msg: "get talent info failed"}
	}

	// 如果达人被拉黑，则返回
	if rec != nil && rec[dao.TalentInfo.Columns.InBlacklist].Int() > 0 {
		return &TalentHttpResult{Code: -6, Msg: "in black list"}
	}

	var newTalentId int64
	if rec == nil {
		// 如果数据库中不存在此达人，则插入新的达人信息
		newTalentId, err = g.DB().Model(dao.TalentInfo.Table).
			Data(g.Map{"talent_wx_openid": wxResp.OpenId, "last_login_date": gtime.Now(),
				"talent_wx_nickname": l.Nickname}).InsertAndGetId()

		if err != nil {
			return &TalentHttpResult{Code: -7, Msg: "add talent info failed"}
		}
	} else {
		// 如果已存在达人，则读取达人id
		newTalentId = rec["id"].Int64()

		// 更新达人最近登录时间
		_, err = g.DB().Model(dao.TalentInfo.Table).Data(
			g.Map{
				"last_login_date": gtime.Now(),
			}).Where("id", newTalentId).Update()
		if err != nil {
			return &TalentHttpResult{Code: -8, Msg: "update talent last login date failed"}
		}
	}

	// 用微信的openid和SessionKey的md5做为token
	token, err := gmd5.EncryptString(wxResp.OpenId + wxResp.SessionKey)
	if err != nil {
		return &TalentHttpResult{Code: -9, Msg: "generate key failed"}
	}

	// 以token为键保存session
	err = r.Session.Set(token, g.Map{
		"talentId":     newTalentId,
		"wxOpenId":     wxResp.OpenId,
		"wxSessionKey": wxResp.SessionKey,
	})

	if err != nil {
		return &TalentHttpResult{Code: -10, Msg: "set session failed"}
	}

	// 生成自己的session_key返回给小程序
	return &TalentHttpResult{Code: 0, Msg: "success", Data: talent_model.LoginResultData{Token: token}}
}