package controllers

import (
	"encoding/json"
	"encoding/xml"
	"fmt"
	"github.com/medivhzhan/weapp/v2"
	adminResp "hongze/hongze_mobile_admin/models/response/admin"
	"hongze/hongze_mobile_admin/models/response/wechat"
	"hongze/hongze_mobile_admin/services"
	"hongze/hongze_mobile_admin/utils"
	"strconv"
	"time"
)

type WeChatCommon struct {
	BaseNotAuth
}

// WeChatLogin
// @Title 微信登录接口
// @Description 微信登录接口
// @Param   Code   query   string  true       "微信唯一编码code"
// @Success 200 {object} wechat.WxLoginResp
// @router /login [get]
func (c *WeChatCommon) WeChatLogin() {
	code := c.GetString("Code")
	fmt.Println("code:", code)
	utils.FileLog.Info("WechatLogin code:%s", code)

	item, err := services.WxGetUserOpenIdByCode(code)
	if err != nil {
		c.FailWithMessage(fmt.Sprintf("%v", err), fmt.Sprintf("%v", err))
		return
	}
	if item.Errcode != 0 {
		c.FailWithMessage("获取用户信息失败", "获取access_token 失败 errCode:"+strconv.Itoa(item.Errcode)+" ;errMsg:"+item.Errmsg)
	}
	openId := item.Openid
	if openId == "" {
		c.FailWithMessage("获取用户信息失败", "获取openid失败,openid:"+item.Openid)
	}
	accessToken, err := services.WxGetAccessToken()
	if err != nil {
		c.FailWithMessage("获取用户信息失败", "获取access_token失败,err:"+err.Error())
	}
	//获取用户信息
	wxUserInfo, err := services.WxGetUserInfo(openId, accessToken)

	if err != nil {
		c.FailWithMessage("获取用户信息失败", "获取微信用户信息失败,Err:"+err.Error())
	}
	if wxUserInfo.Errcode != 0 {
		userInfoJson, _ := json.Marshal(wxUserInfo)
		c.FailWithMessage("登录失败", "获取用户信息失败,err:"+string(userInfoJson))
		return
	}

	token, adminWx, err, errMsg := services.WxLogin(utils.WxPlatform, item, wxUserInfo)
	if err != nil {
		c.FailWithMessage(errMsg, "微信登录失败,err:"+err.Error())
		return
	}

	userInfo := adminResp.LoginResp{
		RealName:       adminWx.RealName,
		AdminName:      adminWx.AdminName,
		RoleName:       adminWx.RoleName,
		RoleTypeCode:   adminWx.RoleTypeCode,
		AdminId:        adminWx.AdminId,
		DepartmentName: adminWx.DepartmentName,
		GroupName:      adminWx.GroupName,
	}

	userInfo.AdminId = adminWx.AdminId
	var productName string
	productId := services.GetProductId(adminWx.RoleTypeCode)

	if productId == 1 {
		productName = utils.COMPANY_PRODUCT_FICC_NAME
	} else if productId == 2 {
		productName = utils.COMPANY_PRODUCT_RAI_NAME
	} else {
		productName = "admin"
	}
	userInfo.ProductName = productName
	userInfo.Authority = adminWx.Authority

	resp := wechat.WxLoginResp{
		AdminId:       adminWx.AdminId,
		Code:          0,
		Authorization: token,
		Headimgurl:    adminWx.Headimgurl,
		RealName:      adminWx.RealName,
		UserInfo:      userInfo,
	}

	//登录日志
	{
		returnResult, err := json.Marshal(resp)
		if err != nil {
			utils.FileLog.Info(c.Ctx.Input.URI() + " Err:%s" + err.Error())
		}
		utils.FileLog.Info(c.Ctx.Input.URI()+" code: %s , return data: %s", code, string(returnResult))
	}

	c.OkDetailed(resp, "登录成功")
}

// WxAppLogin
// @Title 微信登录接口
// @Description 微信登录接口
// @Param   Code   query   string  true       "微信唯一编码code"
// @Success 200 {object} wechat.WxLoginResp
// @router /wxapp/login [get]
func (c *WeChatCommon) WxAppLogin() {
	code := c.GetString("Code")
	if code == "" {
		c.FailWithMessage("参数错误", "Code 为空")
		return
	}
	wxInfo, err := weapp.Login(utils.WxAppId2, utils.WxAppSecret2, code)
	if err != nil {
		c.FailWithMessage("获取用户信息失败", "获取用户信息失败,Err:"+err.Error())
		return
	}
	if err = wxInfo.GetResponseError(); err != nil {
		c.FailWithMessage("获取用户信息失败", "获取用户信息失败,code:"+strconv.Itoa(wxInfo.ErrCode)+",msg:"+wxInfo.ErrMSG)
		return
	}
	item := &services.WxAccessToken{
		//AccessToken  :wxInfo.
		//ExpiresIn    :wxInfo.,
		//RefreshToken : wxInfo,
		Openid:  wxInfo.OpenID,
		Unionid: wxInfo.UnionID,
		//Scope        :wxInfo,
		Errcode: wxInfo.ErrCode,
		Errmsg:  wxInfo.ErrMSG,
	}

	wxUserInfo := new(services.WxUserInfo)
	wxUserInfo.Unionid = wxInfo.UnionID
	wxUserInfo.Openid = wxInfo.OpenID
	wxUserInfo.Unionid = wxInfo.UnionID
	wxUserInfo.Errcode = wxInfo.ErrCode
	wxUserInfo.Errmsg = wxInfo.ErrMSG
	wxUserInfo.SessionKey = wxInfo.SessionKey

	fmt.Println("openId", wxInfo.OpenID)
	fmt.Println("unionId", wxInfo.UnionID)

	token, adminWx, err, errMsg := services.WxLogin(utils.WxPlatform2, item, wxUserInfo)
	if err != nil {
		c.FailWithMessage(errMsg, "微信登录失败,err:"+err.Error())
		return
	}

	userInfo := adminResp.LoginResp{
		RealName:       adminWx.RealName,
		AdminName:      adminWx.AdminName,
		RoleName:       adminWx.RoleName,
		RoleTypeCode:   adminWx.RoleTypeCode,
		AdminId:        adminWx.AdminId,
		DepartmentName: adminWx.DepartmentName,
		GroupName:      adminWx.GroupName,
	}

	userInfo.AdminId = adminWx.AdminId
	var productName string
	productId := services.GetProductId(adminWx.RoleTypeCode)

	if productId == 1 {
		productName = utils.COMPANY_PRODUCT_FICC_NAME
	} else if productId == 2 {
		productName = utils.COMPANY_PRODUCT_RAI_NAME
	} else {
		productName = "admin"
	}
	userInfo.ProductName = productName
	userInfo.Authority = adminWx.Authority

	resp := wechat.WxLoginResp{
		AdminId:       adminWx.AdminId,
		Code:          0,
		Authorization: token,
		Headimgurl:    adminWx.Headimgurl,
		RealName:      adminWx.RealName,
		UserInfo:      userInfo,
	}

	//登录日志
	{
		returnResult, err := json.Marshal(resp)
		if err != nil {
			utils.FileLog.Info(c.Ctx.Input.URI() + " Err:%s" + err.Error())
		}
		utils.FileLog.Info(c.Ctx.Input.URI()+" code: %s , return data: %s", code, string(returnResult))
	}

	c.OkDetailed(resp, "登录成功")
}

// @Title 小程序获取用户信息
// @Description 小程序获取用户信息接口(需要登录)
// @Param	request	body models.WxGetUserInfoReq true "type json string"
// @Success 200 {object} models.WxGetUserInfoResp
// @router /getUserInfo [post]
//func (c *WechatController) GetUserInfo() {
//	br := new(models.BaseResponse).Init()
//	defer func() {
//		c.Data["json"] = br
//		c.ServeJSON()
//	}()
//	var req models.WxGetUserInfoReq
//	err := json.Unmarshal(c.Ctx.Input.RequestBody, &req)
//	if err != nil {
//		br.Msg = "参数解析异常!"
//		br.ErrMsg = "参数解析失败,Err:" + err.Error()
//		return
//	}
//	if req.RawData == "" || req.EncryptedData == "" || req.Signature == "" || req.Iv == "" {
//		br.Msg = "参数错误"
//		return
//	}
//	user := c.User
//	if user == nil {
//		br.Msg = "请登陆"
//		br.Ret = 408
//		return
//	}
//	userId := user.UserId
//	sessionKey := user.SessionKey
//	fmt.Println("sessionKey:", sessionKey)
//	fmt.Println(sessionKey, req.RawData, req.EncryptedData, req.Signature, req.Iv)
//	userInfo, err := weapp.DecryptUserInfo(sessionKey, req.RawData, req.EncryptedData, req.Signature, req.Iv)
//	fmt.Println("weapp.DecryptUserInfo ", err)
//
//	if err != nil {
//		br.Msg = "解析用户信息失败"
//		br.ErrMsg = "解析用户信息失败,DecryptUserInfo Err:" + err.Error()
//		return
//	}
//	//修改用户微信信息
//	err = models.ModifyUserRecordByDetail(userInfo.OpenID, userInfo.UnionID, userInfo.Nickname, userInfo.Avatar, userInfo.City, userInfo.Province, userInfo.Country, userInfo.Gender, userId)
//	if err != nil {
//		br.Msg = "授权失败"
//		br.ErrMsg = "授权失败,修改用户信息失败:" + err.Error()
//		return
//	}
//	var token string
//	tokenItem, err := models.GetTokenByOpenId(userInfo.OpenID)
//	if err != nil && err.Error() != utils.ErrNoRow() {
//		br.Msg = "授权失败"
//		br.ErrMsg = "授权失败,获取token失败:" + err.Error()
//		return
//	}
//
//	if tokenItem == nil || (err != nil && err.Error() == utils.ErrNoRow()) {
//		timeUnix := time.Now().Unix()
//		timeUnixStr := strconv.FormatInt(timeUnix, 10)
//		token = utils.MD5(userInfo.OpenID) + utils.MD5(timeUnixStr)
//		//新增session
//		{
//			session := new(models.CygxSession)
//			session.OpenId = userInfo.OpenID
//			session.UnionId = userInfo.UnionID
//			session.UserId = userId
//			session.CreatedTime = time.Now()
//			session.LastUpdatedTime = time.Now()
//			session.ExpireTime = time.Now().AddDate(0, 3, 0)
//			session.AccessToken = token
//			err = models.AddSession(session)
//			if err != nil {
//				br.Msg = "授权失败"
//				br.ErrMsg = "授权失败,新增用户session信息失败:" + err.Error()
//				return
//			}
//		}
//	} else {
//		token = tokenItem.AccessToken
//	}
//	resp := new(models.WxGetUserInfoResp)
//	resp.Authorization = token
//	br.Msg = "获取成功!"
//	br.Ret = 200
//	br.Success = true
//}

// AdminWeChatLogin
// @Title 内部员工公众号(弘则部门)微信绑定接口
// @Description 内部员工公众号(弘则部门)微信绑定接口
// @Param   Code   query   string  true       "微信唯一编码code"
// @Success 200 {object} wechat.WxLoginResp
// @router /admin/login [get]
func (c *WeChatCommon) AdminWeChatLogin() {
	code := c.GetString("Code")
	fmt.Println("code:", code)
	utils.FileLog.Info("WechatLogin code:%s", code)

	item, err := services.WxGetAdminOpenIdByCode(code)
	if err != nil {
		c.FailWithMessage(fmt.Sprintf("%v", err), fmt.Sprintf("%v", err))
		return
	}
	if item.Errcode != 0 {
		if item.Errcode == 40163 {
			c.FailWithCodeUsed("获取用户信息失败", "获取access_token 失败 errCode:"+strconv.Itoa(item.Errcode)+" ;errMsg:"+item.Errmsg)
			return
		}
		c.FailWithMessage("获取用户信息失败", "获取access_token 失败 errCode:"+strconv.Itoa(item.Errcode)+" ;errMsg:"+item.Errmsg)
		return
	}
	openId := item.Openid
	if openId == "" {
		c.FailWithMessage("获取用户信息失败", "获取openid失败,openid:"+item.Openid)
		return
	}
	accessToken, err := services.WxGetRedisAccessToken(utils.AdminWxAppId, utils.AdminWxAppSecret)
	if err != nil {
		c.FailWithMessage("获取用户信息失败", "获取access_token失败,err:"+err.Error())
	}
	//获取用户信息
	wxUserInfo, err := services.WxGetUserInfo(openId, accessToken)
	if err != nil {
		c.FailWithMessage("获取用户信息失败", "获取微信用户信息失败,Err:"+err.Error())
		return
	}
	userInfoJson, _ := json.Marshal(wxUserInfo)
	utils.FileLog.Info("services.WxGetUserInfo:%s", string(userInfoJson))
	if wxUserInfo.Errcode != 0 {
		c.FailWithMessage("登录失败", "获取用户信息失败,err:"+string(userInfoJson))
		return
	}
	/*item := &services.WxAccessToken{
		AccessToken:  "",
		ExpiresIn:    0,
		RefreshToken: "",
		Openid:       "openid1231243124343",
		Unionid:      "unionid123123123",
		Scope:        "",
		Errcode:      0,
		Errmsg:       "",
	}

	wxUserInfo := &services.WxUserInfo{
		Openid:         "openid1231243124343",
		Nickname:       "",
		Sex:            0,
		Language:       "",
		City:           "",
		Province:       "",
		Country:        "",
		Headimgurl:     "",
		SubscribeTime:  0,
		Unionid:        "unionid123123123",
		Remark:         "",
		Groupid:        0,
		SubscribeScene: "",
		SessionKey:     "",
		Errcode:        0,
		Errmsg:         "",
	}*/
	resp, err, errMsg := services.AdminWxLogin(item, wxUserInfo)
	if err != nil {
		c.FailWithMessage(errMsg, "微信登录失败,err:"+err.Error())
		return
	}

	//登录日志
	{
		returnResult, err := json.Marshal(resp)
		if err != nil {
			utils.FileLog.Info(c.Ctx.Input.URI() + " Err:%s" + err.Error())
		}
		utils.FileLog.Info(c.Ctx.Input.URI()+" code: %s , return data: %s", code, string(returnResult))
	}

	c.OkDetailed(resp, "登录成功")
}

// @Title 微信获取签名接口
// @Description 微信获取签名接口
// @Param   Url   query   string  true       "url地址"
// @Success 200 {object} models.WechatSign
// @router /notify [get,post]
func (c *WeChatCommon) Notify() {
	echostr := c.GetString("echostr")
	method := c.Ctx.Input.Method()
	if method == "POST" {
		body := c.Ctx.Input.RequestBody
		utils.FileLog.Info("wechat notify:" + string(body))
		item := new(Notify)
		err := xml.Unmarshal(body, &item)
		if err != nil {
			utils.FileLog.Info("xml.Unmarshal:" + err.Error())
		}
		contactMsg := "感谢关注弘则内部。\n\n此公众号仅供内部员工使用,用于内部员工接收消息通知"

		var openId, returnResult string
		if item.MsgType != "" {
			openId = item.FromUserName
		}
		xmlTpl := `<xml>
		<ToUserName><![CDATA[%s]]></ToUserName>
		<FromUserName><![CDATA[%s]]></FromUserName>
		<CreateTime>%s</CreateTime>
		<MsgType><![CDATA[text]]></MsgType>
		<Content><![CDATA[%s]]></Content>
		</xml>`
		createTime := strconv.FormatInt(time.Now().Unix(), 10)
		xmlTpl = fmt.Sprintf(xmlTpl, openId, utils.WxId, createTime, contactMsg)

		if item.MsgType == "event" {
			switch item.Event {
			case "subscribe":
				fmt.Println("关注")
			//	go models.UserSubscribe(1, openId)
				break
			case "unsubscribe":
				fmt.Println("取消关注")
			//	go models.UserSubscribe(0, openId)
				break
			case "CLICK":
				returnResult = xmlTpl
				break
			default:
				utils.FileLog.Info("wechat notify event:" + item.Event)
			}
			c.Ctx.WriteString(xmlTpl)
		} else {
			returnResult = xmlTpl
		}
		c.Ctx.WriteString(returnResult)
	} else {
		c.Ctx.WriteString(echostr)
	}
}

type Notify struct {
	ToUserName   string `xml:"ToUserName"`
	FromUserName string `xml:"FromUserName"`
	CreateTime   int    `xml:"CreateTime"`
	MsgType      string `xml:"MsgType"`
	Event        string `xml:"Event"`
	EventKey     string `xml:"EventKey"`
}