package middleware

import (
	"bytes"
	"encoding/base64"
	"fmt"
	"gin-vue-admin/global"
	"gin-vue-admin/utils"
	"go.uber.org/zap"
	"io/ioutil"
	"net/http"

	"github.com/gin-gonic/gin"
)

type EncryptParam struct {
	EncryptedData string `json:"encrypted_data" form:"encrypted_data"`
}

type EncryptResponseWriter struct {
	gin.ResponseWriter
	Buff *bytes.Buffer
}

func (e *EncryptResponseWriter) Write(p []byte) (int, error) {
	return e.Buff.Write(p)
	//return e.ResponseWriter.Write(p) // 不再写底层的这个write
}

//加密
func AesEncrypt() gin.HandlerFunc {
	return func(c *gin.Context) {
		cert := global.GVA_CONFIG.Encrypt // 此处是从数据库读取certs, 也可以本地读取文件
		data := []byte("{\"city\":\"沈阳市\",\"county\":\"浑南区\",\"detail\":\"彩霞街融城时代1期1号楼6单元\",\"goodsId\":11057,\"name\":\"刘博宇\",\"phone\":\"18600806871\",\"policyNo\":\"T210914000000120130707\",\"province\":\"辽宁省\"}")
		xpass, err := utils.AesEncrypt(data, []byte(cert.Key))
		if err != nil {
			fmt.Println(err)
			return
		}

		pass64 := base64.StdEncoding.EncodeToString(xpass)
		fmt.Printf("加密后:%v\n",pass64)
		c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(xpass))

		c.Next()

		return
	}
}

//解密
func AesDecrypt() gin.HandlerFunc {
	return func(c *gin.Context) {

		encryptWriter := &EncryptResponseWriter{c.Writer, bytes.NewBuffer(make([]byte, 0))}
		c.Writer = encryptWriter

		param := EncryptParam{}
		if err := c.Bind(&param); err != nil {
			c.AbortWithStatus(http.StatusBadRequest)
			global.GVA_LOG.Error("Bind EncryptParam!", zap.Any("err", err))
			c.JSON(http.StatusOK, gin.H{
				"code": 400,
				"msg":  "数据有误",
				"data": nil,
			})
			c.Abort()
		}

		cert := global.GVA_CONFIG.Encrypt // 此处是从数据库读取certs, 也可以本地读取文件

		bytesPass, err := base64.StdEncoding.DecodeString(param.EncryptedData)
		if err != nil {
			global.GVA_LOG.Error("err!", zap.Any("err", err))
			c.JSON(http.StatusOK, gin.H{
				"code": 400,
				"msg":  "数据有误",
				"data": nil,
			})
			c.Abort()
		}

		tpass, err := utils.AesDecrypt(bytesPass, []byte(cert.Key))
		if err != nil {
			global.GVA_LOG.Error("err!", zap.Any("err", err))
			c.JSON(http.StatusOK, gin.H{
				"code": 400,
				"msg":  "数据有误",
				"data": nil,
			})
			c.Abort()
		}
		fmt.Printf("解密后:%s\n", tpass)

		c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(tpass))

		c.Next()

		normalReturn := func() {
			if _, err := encryptWriter.ResponseWriter.Write(encryptWriter.Buff.Bytes()); err != nil {

				global.GVA_LOG.Error("err!", zap.Any("err", err))
				c.JSON(http.StatusOK, gin.H{
					"code": 400,
					"msg":  "数据有误",
					"data": nil,
				})
				c.Abort()
			}
		}
		if encryptWriter.Status() != http.StatusOK { // 不成功, 直接返回
			normalReturn()
			c.Abort()
		}

		normalReturn()
		return
	}
}

// AES加密
func AesEncryptData(key, data string) (res string, err error) {
	eData,err := utils.AesEncrypt([]byte(data), []byte(key))
	res = base64.URLEncoding.EncodeToString(eData)
	return
}

// AES解密
func AesDecryptData(key, data string) (res string, err error) {
	eData, err := base64.StdEncoding.DecodeString(data)
	fmt.Println(eData)
	fmt.Println(err)
	if err != nil {
		return
	}
	context,err := utils.AesDecrypt(eData, []byte(key))
	res = string(context)
	return
}

// recover错误，转string
func errorToString(r interface{}) string {
	switch v := r.(type) {
	case error:
		return v.Error()
	default:
		return r.(string)
	}
}