package controllers

import (
	"encoding/hex"
	"encoding/json"
	"fmt"
	"github.com/astaxie/beego"
	"gitlab.fjmaimaimai.com/mmm-go/gocomm/pkg/mybeego"
	"gitlab.fjmaimaimai.com/mmm-go/gocomm/pkg/log"
	"github.com/astaxie/beego/httplib"
	"io/ioutil"
	"net/http"
	"path"
	"reflect"
	"strings"
)

type ABController struct {
	BaseController
}

var aHost string
var bHost string

const (
	QueryResponseError = 1  //请求应答错误
	CompareResultError=2 //应答对比错误
)

func init(){
	aHost =beego.AppConfig.String("AHost")
	bHost =beego.AppConfig.String("BHost")
}

//Compare
func(this *ABController)Compare(){
	var (
		msg *mybeego.Message
		status string = "OK"
	)
	defer func(){
		this.Resp(msg)
	}()
	method := this.Ctx.Request.Method
	head :=this.Ctx.Request.Header
	body :=this.ByteBody
	newRequest:= NewRequest(bHost,method,head,body)
	aResp,err :=makeHttpRequest(aHost,method,head,body)
	if err!=nil{
		status ="FAIL"
	}
	log.Debug(fmt.Sprintf("[%v]- Method:%v \n Head:\n%v \nBody:\n%v \n Response:\n%v",status,method,head,body,aResp))
	this.Data["json"] = aResp

	Compare :=func(){
		defer func(){
			if p:=recover();p!=nil{
				log.Error(p)
			}
		}()
		//判断已经在错误列表里面就不再判断请求
		bResp,err :=makeHttpRequest(bHost,method,head,body)
		if err!=nil{
			log.Error(err)
			errorHandler(QueryResponseError,newRequest)
			return
		}
		cResult,err :=compareResponse(aResp,bResp)
		if err!=nil{
			log.Error(err)
			errorHandler(QueryResponseError,newRequest)
			return
		}
		if !cResult{
			errorHandler(CompareResultError,newRequest)
			log.Warn(fmt.Sprintf("" +
				"[Companre Error] - ErrorType:%v " +
				"\nMethod:\n %v " +
				"\nHead:\n %v " +
				"\nAResponse:\n %v  " +
				"\nBResponse:\n %v",CompareResultError,method,head,string(aResp),string(bResp)))
		}else{
			//记录到记录行里面
			log.Info("[Success] \nMethod:\n %v " +
				"\nHead:\n %v " +
				"\nBody:\n%v",method,head,string(body))
		}
	}

	go Compare()
	this.ServeJSON()
}
func compareResponse(aResp,bResp []byte)(result bool,err error){
	defer func(){
		if p:=recover();p!=nil{
			log.Error(p)
		}
	}()
	var mapA = make(map[string]interface{})
	var mapB = make(map[string]interface{})

	if err =json.Unmarshal(aResp,&mapA);err!=nil{
		result = false
		return
	}
	if err =json.Unmarshal(bResp,&mapB);err!=nil{
		result = false
		return
	}
	result = reflect.DeepEqual(mapA,mapB)
	return
}
func errorHandler(errType int,req Request){
	//写redis error
}
func makeHttpRequest(host,method string,head map[string][]string,body []byte)(data []byte,err error){
	var (
		resp *http.Response
	)
	rawUrl := path.Join(host,method)
	req := httplib.NewBeegoRequest(rawUrl,"Post")
	for k,v:=range head{
		req.Header(k,strings.Join(v,","))
	}
	req.Body(body)
	resp,err =req.DoRequest()
	if err!=nil{
		return
	}
	data,err = ioutil.ReadAll(resp.Body)
	defer resp.Body.Close()
	return
}


type Request struct {
	Host string
	Method string
	Head map[string][]string
	Body string //hex
}
func NewRequest(host,method string,head map[string][]string,body []byte)Request{
	return Request{
		Host:host,
		Method:method,
		Head:head,
		Body:hex.EncodeToString(body),
	}
}
func(req Request)GetBody()([]byte){
	data,err:= hex.DecodeString(req.Body)
	if err!=nil{
		log.Error(err)
		return []byte{}
	}
	return data
}