package controllers

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"io/ioutil"
	"net/http"
	"wechat-conf/models"
	"wechat-conf/models/model"
	"wechat-conf/service/autoreply"
	"wechat-conf/service/wechat"
	"wechat-conf/utils"

	"github.com/astaxie/beego"

	"github.com/kinisky564477/wechat/component"

	"github.com/kinisky564477/wechat/core"
)

// WechatController 用户
type WechatController struct {
	BaseController
	serv       *autoreply.AutoreplyServ
	wechatServ *wechat.WechatServ
}

// Constructor 初始化 Controller
// @Title Constructor
// @Description 初始化 Controller, 系统自动调用
func (c *WechatController) Constructor() {
	c.serv = autoreply.NewAutoreplyServ(c.Context)
	c.wechatServ = wechat.NewWechatServ(c.Context)
}

const (
	INFOTYPE_TICKET           = "component_verify_ticket"
	INFOTYPE_AUTHORIZED       = "authorized"
	INFOTYPE_UNAUTHORIZED     = "unauthorized"
	INFOTYPE_UPDATEAUTHORIZED = "updateauthorized"
)

// ComponentPush 第三方平台推送
func (c *WechatController) ComponentPush() {
	utils.LogError("推送开始")
	r := c.Ctx.Request
	defer r.Body.Close()
	con, _ := ioutil.ReadAll(r.Body)
	utils.LogError("推送消息:", string(con))
	// 解析xml
	xp := &core.XMLParse{}
	resMsg, err := xp.Parse(string(con))
	if err != nil {
		utils.LogError("xml解析失败:", err)
		c.ResponseRaw([]byte("success"))
	}
	encrypt := resMsg["Encrypt"]
	conf, err := c.wechatServ.GetComponentInfo()
	if err != nil || conf == nil || conf.Appid == "" {
		utils.LogError("读取微信配置文件失败")
		c.ResponseRaw([]byte("success"))
	}
	EncodingAESKey := conf.Aeskey

	AESKey, err := base64.StdEncoding.DecodeString(EncodingAESKey + "=")
	if err != nil {
		utils.LogError("DecodeString失败:", err)
		c.ResponseRaw([]byte("success"))
	}
	EncryptVal, err := base64.StdEncoding.DecodeString(encrypt)
	if err != nil {
		utils.LogError("密文base64解析", err)
		c.ResponseRaw([]byte("success"))
	}
	msgbyte, err := utils.AesDecrypt(EncryptVal, AESKey)
	if err != nil {
		utils.LogError("解密失败:", err)
		c.ResponseRaw([]byte("success"))
	}
	utils.LogError("解密成功")
	// 解析xml
	msg, err := xp.Parse(string(msgbyte))
	if err != nil {
		utils.LogError("xml解析失败:", err)
		c.ResponseRaw([]byte("success"))
	}
	utils.LogError("xml解析成功:", msg)
	switch msg["InfoType"] {
	case INFOTYPE_TICKET:
		// 更新ticket
		conf.Ticket = msg["ComponentVerifyTicket"]
		err := c.wechatServ.UpdateComponentTicket(conf)
		if err != nil {
			utils.LogError("修改ticket失败:", err)
		}
		utils.RefreshComponentTicket(msg["ComponentVerifyTicket"])
		break
	case INFOTYPE_AUTHORIZED:
		// 授权成功
		var cert = map[string]string{
			"appid":              msg["AuthorizerAppid"],
			"authorization_code": msg["AuthorizationCode"],
		}
		beego.Error("授权成功参数:", cert)
		wxclient := utils.WechatInit(cert, c.wechatServ.UpdateToken)
		if wxclient == nil {
			utils.LogError("获取wxclient失败")
			c.ResponseRaw([]byte("success"))
		}
		beego.Error(wxclient)
		utils.AppendWxClient(wxclient)

		// 获取微信信息
		info, err := wxclient.GetWechatInfo()
		if err != nil {
			utils.LogError("获取微信信息失败")
			c.ResponseRaw([]byte("success"))
		}
		beego.Error(info)
		authorizerInfo := (info["authorizer_info"]).(map[string]interface{})
		beego.Error(info["authorizer_info"])
		// 插入数据库
		mjson, _ := json.Marshal(msg)
		HeadImg := ""
		if authorizerInfo["head_img"] != nil {
			HeadImg = authorizerInfo["head_img"].(string)
		}
		var conf = model.SysWechatConf{
			Appid:             msg["AuthorizerAppid"],
			AuthorizationCode: msg["AuthorizationCode"],
			AuthorizationInfo: string(mjson),
			WxNikeName:        authorizerInfo["nick_name"].(string),
			HeadImg:           HeadImg,
			UserName:          authorizerInfo["user_name"].(string),
			PrincipalName:     authorizerInfo["principal_name"].(string),
			QrcodeUrl:         authorizerInfo["qrcode_url"].(string),
		}

		err = c.wechatServ.SaveWechatConf(conf)
		if err != nil {
			utils.LogError("保存微信授权信息失败:", err)
			c.ResponseRaw([]byte("success"))
		}
		break
	case INFOTYPE_UPDATEAUTHORIZED:
		// 授权更新
		break
	case INFOTYPE_UNAUTHORIZED:
		// 取消授权
		// 删除wechatConf信息,同时将org解绑
		appid := msg["AuthorizerAppid"]
		c.wechatServ.UnAuthorized(appid)
		// 删除第三方中的微信信息
		utils.Component.DelWxClient(appid)
		break
	}
	c.ResponseRaw([]byte("success"))
}

// WechatInfo 微信接入
func (c *WechatController) WechatInfo() {
	method := c.Ctx.Input.Method()
	if method == http.MethodGet {
		echostr := c.GetString("echostr")
		c.ResponseRaw([]byte(echostr))
	} else {
		c.WxReceive()
	}
}

// WxReceive 微信消息接收
func (c *WechatController) WxReceive() {
	beego.Error("微信消息接入")
	appid := c.GetString(":appid")
	wechat, err := utils.Component.GetWxClient(appid)
	if err != nil {
		utils.LogError("获取微信失败: " + err.Error())
	}
	msg, err := wechat.TransformMessage(string(c.Ctx.Input.RequestBody))
	if err != nil {
		utils.LogError("读取微信服务发送内容失败: " + err.Error())
		c.ResponseRaw([]byte(""))
	}
	xp := &core.XMLParse{}
	beego.Error("消息:", msg)
	encrypt := msg["Encrypt"]
	conf, err := c.wechatServ.GetComponentInfo()
	if err != nil || conf == nil || conf.Appid == "" {
		utils.LogError("读取微信配置文件失败")
		c.ResponseRaw([]byte("success"))
	}
	EncodingAESKey := conf.Aeskey

	AESKey, err := base64.StdEncoding.DecodeString(EncodingAESKey + "=")
	if err != nil {
		utils.LogError("DecodeString失败:", err)
		c.ResponseRaw([]byte("success"))
	}
	EncryptVal, err := base64.StdEncoding.DecodeString(encrypt)
	if err != nil {
		utils.LogError("密文base64解析", err)
		c.ResponseRaw([]byte("success"))
	}
	msgbyte, err := utils.AesDecrypt(EncryptVal, AESKey)
	if err != nil {
		utils.LogError("解密失败:", err)
		c.ResponseRaw([]byte("success"))
	}
	utils.LogError("解密成功")
	// 解析xml
	val, err := xp.Parse(string(msgbyte))
	if err != nil {
		utils.LogError("xml解析失败:", err)
		c.ResponseRaw([]byte("success"))
	}
	utils.LogError("xml解析成功:", val)
	var replay = new(model.TaAutoReply)
	switch val["MsgType"] {
	case "text":
		content := val["Content"]
		// 获取数据库存储返回类型
		replay, err = c.serv.GetAutoReplayByAppID(appid, content)
		break
	case "event":
		beego.Error(val)
		switch val["Event"] {
		case "subscribe":
			replay, err = c.serv.GetSubscribeByAppID(appid)
			break
		case "LICK":
			// 点击事件

		}

		break
	}
	if err != nil {
		utils.LogError("获取微信自动回复信息失败: " + err.Error())
		c.ResponseRaw([]byte(""))
	}
	if replay == nil {
		c.ResponseRaw([]byte(""))
	}
	openID := val["FromUserName"]
	message, err := c.getReplayMessage(replay, openID, wechat)
	if err != nil {
		utils.LogError("转换回复信息失败: " + err.Error())
		c.ResponseRaw([]byte(""))
	}

	cipher, err := core.NewCipher(utils.Component.GetToken(), EncodingAESKey, appid)
	if err != nil {
		utils.LogError("获取解密失败: " + err.Error())
		c.ResponseRaw([]byte(""))
	}

	dt := bytes.NewBuffer([]byte{})
	cipher.Encrypt(dt, []byte(message))
	beego.Error("=========>", dt)

	c.ResponseRaw(dt.Bytes())
	// c.ResponseRaw([]byte("success"))
}

func (c *WechatController) getReplayMessage(replay *model.TaAutoReply, openid string, wx *component.WxClient) ([]byte, error) {
	switch replay.MessageType {
	case models.MESSAGE_TYPE_PARAGRAPH:
		msg, err := wx.ResponseMessageText(openid, replay.MessageParagraph)
		return msg, err
	case models.MESSAGE_TYPE_IMG:
		msg, err := wx.ResponseMessageImage(openid, replay.MessageImg)
		return msg, err
		// case models.MESSAGE_TYPE_PARAGRAPH:
		// 	msg, err := wx.ResponseMessageNews(openid, replay.MessageImg)
		// 	return msg, err
	}
	return nil, nil
}

// GetPreAuthCode 获取预授权码
func (c *WechatController) GetPreAuthCode() {
	code, err := utils.Component.GetPreAuthCode()
	if err != nil {
		utils.LogError("获取预授权码错误: " + err.Error())
		c.ResponseError(err)
	}
	appid := utils.Component.GetCertificate()["appid"]
	c.ResponseJSON(map[string]string{
		"appid": appid,
		"code":  code,
	})
}

// GetWechatMenuByAppID 根据appid获取微信详情
func (c *WechatController) GetWechatInfoByAppID() {
	appid := c.GetString(":appid")
	wxclient, err := utils.Component.GetWxClient(appid)
	if err != nil {
		utils.LogError("获取微信信息失败: " + err.Error())
		c.ResponseError(err)
	}
	info, err := wxclient.GetWechatInfo()
	if err != nil {
		utils.LogError("获取微信详情失败: " + err.Error())
		c.ResponseError(err)
	}
	c.ResponseJSON(info)
}

// GetWechatMenuByAppID 获取菜单
func (c *WechatController) GetMaterialByAppID() {
	appid := c.GetString(":appid")
	wxclient, err := utils.Component.GetWxClient(appid)
	if err != nil {
		utils.LogError("获取微信信息失败: " + err.Error())
		c.ResponseError(err)
	}
	var data = map[string]string{}
	data["offset"] = "0"
	data["type"] = "image"
	data["count"] = "10"

	menus, err := wxclient.GetMaterialList(data)
	if err != nil {
		utils.LogError("获取微信详情失败: " + err.Error())
		c.ResponseError(err)
	}
	c.ResponseJSON(menus)
}

// GetWechatByCode 根据code获取微信信息
func (c *WechatController) GetWechatByCode() {
	code := c.GetString(":code")
	beego.Error(code)
	conf, err := c.wechatServ.GetWechatByCode(code)
	if err != nil {
		utils.LogError("获取微信详情失败: " + err.Error())
		c.ResponseError(err)
	}
	beego.Error(conf)
	if conf == nil || conf.ConfId == "" || conf.Status == models.STATUS_NORMAL {
		c.ResponseJSON("")
	}

	c.ResponseJSON(map[string]string{
		"ConfId":   conf.ConfId,
		"NickName": conf.WxNikeName,
		"HeadImg":  conf.HeadImg,
	})
}