package controllers

import (
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/context"
	"github.com/astaxie/beego/validation"
	"gitlab.fjmaimaimai.com/mmm-go/ability/protocol"
	"gitlab.fjmaimaimai.com/mmm-go/ability/services/auth"
	"gitlab.fjmaimaimai.com/mmm-go/gocomm/common"
	"gitlab.fjmaimaimai.com/mmm-go/gocomm/pkg/log"
	"gitlab.fjmaimaimai.com/mmm-go/gocomm/pkg/mybeego"
	"strconv"

	//"strconv"
	"strings"
)

type BaseController struct {
	mybeego.BaseController
}
var DefaultController *BaseController = &BaseController{}
//Valid  valid struct
func (this *BaseController)Valid(obj interface{})(result bool ,msg *mybeego.Message){
	/*校验*/
	var err error
	valid :=validation.Validation{}
	result,err= valid.Valid(obj)
	if err!=nil{
		msg = mybeego.NewMessage(1)
		return
	}
	if !result{
		for _, err := range valid.Errors {
			log.Error(err.Key, err.Message)
		}
		msg = mybeego.NewMessage(2)
		return
	}
	return
}

//GenMessage genarate a response message
func (this *BaseController)GenMessage(rsp interface{},err error)*mybeego.Message{
	var msg *mybeego.Message
	if err==nil{
		msg = mybeego.NewMessage(0)
		msg.Data = rsp
		return msg
	}
	log.Error(err)
	if e,ok :=err.(common.Error);ok{
		msg = mybeego.NewMessage(e.Code)
		msg.Data = rsp
		return msg
	}
	msg = mybeego.NewMessage(1)
	return msg
}

func GetRequestHeader(ctx *context.Context)*protocol.RequestHeader{
	h :=&protocol.RequestHeader{}
	h.AccessToken = ctx.Input.Header("x-mmm-accesstoken")
	h.AppProject = ctx.Input.Header("x-mmm-appproject")
	h.DeviceType = ctx.Input.Header("x-mmm-devicetype")
	h.Sign = ctx.Input.Header("x-mmm-sign")
	h.Uuid = ctx.Input.Header("x-mmm-uuid")
	h.TimeStamp = ctx.Input.Header("x-mmm-timestamp")
	h.Uid,_=strconv.ParseInt(ctx.Input.Header("uid"),10,64)//需要uid写入到header里面
	return h
}

func FilterComm(ctx *context.Context){
	if strings.HasSuffix(ctx.Request.RequestURI,"login"){
		return
	}
	if beego.BConfig.RunMode!="prod"{
		return
	}
	//1.检查签名
	if !CheckSign(ctx){
		return
	}
	//2.检查token是否有效
	if !CheckToken(ctx){
		return
	}
	//3.查重uuid
	if !CheckUuid(ctx){
		return
	}
	return
}
//检查签名
func CheckSign(ctx *context.Context)(result bool){
	var(
		h *protocol.RequestHeader
		sign string
		signHex string
	)
	result = true
	h =GetRequestHeader(ctx)
	//1.检查签名
	sign =fmt.Sprintf("v!(MmM%v%v%vMmM)i^",h.TimeStamp,h.Uuid,h.AccessToken)
	sha256:=sha256.New()
	sha256.Write([]byte(sign))
	signHex = hex.EncodeToString(sha256.Sum(nil))
	if strings.Compare(signHex,h.Sign)!=0{
		msg :=mybeego.NewMessage(113)
		log.Error(fmt.Sprintf("%v req:%v resp:%v %v",ctx.Request.RequestURI,common.AssertJson(h),common.AssertJson(msg),signHex))
		ctx.Output.JSON(msg, false, false)
		result =false
		return
	}
	return
}
//检查access_token
func CheckToken(ctx *context.Context)(result bool){
	var (
		msg *mybeego.Message
	)
	result = true
	defer func(){
		if msg!=nil{
			result =false
			ctx.Output.JSON(msg,false,false)
		}
	}()
	token := ctx.Input.Header("x-mmm-accesstoken")
	if rsp,err:=auth.CheckToken(&protocol.CheckTokenRequest{Token:token});(err!=nil || rsp.UserInfo==nil){
		msg = DefaultController.GenMessage(rsp,err)
		log.Error(fmt.Sprintf("%v req:%v resp:%v",ctx.Request.RequestURI,token,common.AssertJson(msg)))
		return
	}else{
		if rsp.UserInfo!=nil{
			//设置附加数据
			ctx.Request.Header.Add("uid",fmt.Sprintf("%v",rsp.UserInfo.Uuid))
		}
	}
	return
}
//检查Uuid
func CheckUuid(ctx *context.Context)(result bool){
	var (
		msg *mybeego.Message
	)
	result = true
	defer func(){
		if msg!=nil{
			result =false
			ctx.Output.JSON(msg,false,false)
		}
	}()
	uuid :=  ctx.Input.Header("x-mmm-uuid")
	msg = DefaultController.GenMessage(auth.CheckUuid(&protocol.CheckUuidRequest{Uuid:uuid}))
	if msg!=nil{
		log.Error(fmt.Sprintf("%v req:%v resp:%v",ctx.Request.RequestURI,uuid,common.AssertJson(msg)))
	}
	return
}