package middleware

import (
	"app.yhyue.com/moapp/jybase/common"
	log "app.yhyue.com/moapp/jylog"
	. "bp.jydev.jianyu360.cn/BaseService/gateway/common/gatecode"
	"bp.jydev.jianyu360.cn/BaseService/gateway/common/httpUtil"
	"bp.jydev.jianyu360.cn/BaseService/gateway/core/proxy/filterPoly"
	"bp.jydev.jianyu360.cn/BaseService/gateway/core/router"
	"bp.jydev.jianyu360.cn/BaseService/gateway/core/util"
	"fmt"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/net/ghttp"
	"github.com/gogf/gf/v2/net/gtrace"
	"github.com/gogf/gf/v2/util/gconv"
	"net/http"
	"strings"
)

const (
	defaultVerifyPageHtml = "default"
	VerifyPageHtmlSource  = "./resources/antiRes/page/%s.html"

	JyAntiEncryptSign = "antiEncrypt"
	JySecretKey       = "secretKey"
)

var filterPolyManager *filterPoly.Manager

func InitFilterPolyManager() {
	filterPolyManager = filterPoly.InitFilterPolyManager()
}

func FilterPolyHandler(r *ghttp.Request) {
	func() {
		ctx, span := gtrace.NewSpan(r.Context(), "FilterPolyHandler")
		defer span.End()

		gCtx := router.GetGContext(ctx)
		//获取策略
		poly := filterPolyManager.GetRule(gCtx.RouterRule.LimitPloy)
		status, key, uid, inWhite := func() (status int, checkKey, userFlag string, inWhite bool) {
			//用户身份切换
			userFlag, _ = common.If(gCtx.Sess.MgoUserId != "", gCtx.Sess.MgoUserId, gCtx.Sess.UserId).(string)
			if userFlag != "" && poly.Rule.BCheckId { //id请求频率校验
				status, checkKey, inWhite = poly.IdFilter(ctx, userFlag)
				return
			} else { //ip请求频率校验
				status, checkKey, inWhite = poly.IpFilter(ctx, r.GetClientIp())
				return
			}
		}()
		returnHtml := false
		if strings.Contains(strings.ToLower(r.Header.Get("Accept")), "html") {
			returnHtml = true
		}
		//是否开启黑名单
		if status == -1 { //黑名单 不响应
			r.SetError(NewErrorWithCode(OTHER_ERR_OFTEN, fmt.Sprintf("请求频繁限制")))
			r.Response.ResponseWriter.WriteHeader(403)
			return
		}
		if status == 2 { //处理验证码逻辑
			rData := poly.VerifyHandle(r, key, uid != "")
			if !returnHtml {
				r.Response.WriteJsonExit(rData)
			} else {
				if renderErr := httpUtil.Render(r.Response.ResponseWriter, getVerifyPage(poly.Rule.VerifyPage), &rData); renderErr != nil {
					r.SetError(NewErrorWithCode(GATEWAY_HTML_RENDER_ERR, fmt.Sprintf("验证码页面:%v\n", renderErr)))
				}
			}
			return
		}
		//处理相应内容加
		if !inWhite && poly.Rule.JsEncrypt == 1 {
			if !returnHtml {
				r.SetCtxVar("changeFunc", SpiderJsEncrypt)
			}
		}
	}()
	r.Middleware.Next()
}

// getVerifyPage 获取验证码页面路径
func getVerifyPage(page string) string {
	if page != "" {
		if strings.HasSuffix(page, ".html") {
			page = strings.ReplaceAll(page, ".html", "")
		}
		return fmt.Sprintf(VerifyPageHtmlSource, page)
	} else {
		return fmt.Sprintf(VerifyPageHtmlSource, defaultVerifyPageHtml)
	}
}

// SpiderJsEncrypt 反爬虫加密相应内容
func SpiderJsEncrypt(resp *http.Response) error {
	return util.ChangeResponse(resp, func(bytes []byte) (newBytes []byte, err error) {
		if len(bytes) == 0 {
			return nil, nil
		}
		var entryStr, PKeyStr string
		entryStr, PKeyStr, err = util.JyAntiEncrypt(bytes)
		if err != nil {
			log.Println("JyAntiEncrypt err: ", err.Error())
			return
		}
		newBytes = gconv.Bytes(g.Map{
			JyAntiEncryptSign: 1,
			JySecretKey:       PKeyStr,
			"data":            entryStr,
		})
		resp.Header.Add(JyAntiEncryptSign, "1")
		//resp.Header.Add(JySecretKey, PKeyStr)
		return
	})
}
