package service

import (
	"encoding/base64"
	"encoding/json"
	"fmt"
	"github.com/go-kratos/kratos/v2/log"
	"github.com/go-kratos/kratos/v2/transport/http"
	"io"
	http2 "net/http"
	"voucher/internal/biz"
	"voucher/internal/biz/bo"
	"voucher/internal/conf"
	"voucher/internal/pkg/helper"
	"voucher/internal/pkg/supplier/qixing"
)

type TripartiteService struct {
	bc       *conf.Bootstrap
	multiBiz *biz.MultiBiz
}

func NewTripartiteService(bc *conf.Bootstrap, multiBiz *biz.MultiBiz) *TripartiteService {
	return &TripartiteService{bc: bc, multiBiz: multiBiz}
}

// QiXingNotify
// 重试规则
// 1.重试间隔：每次推送失败后，间隔5分钟重新推送；
// 2.最大重试次数：累计推送5 次（首次 + 4 次重试；
// 3.停止条件：返回成功响应 或 达到 4 次重试上限，停止推送。
func (srv *TripartiteService) QiXingNotify(ctx http.Context) error {

	ip := helper.GetClientIP(ctx)
	if ip == "" {
		return fmt.Errorf("获取请求 IP 失败")
	}

	bodyBytes, err := io.ReadAll(ctx.Request().Body)
	if err != nil {
		return srv.ResponseErr(ctx, fmt.Sprintf("read body error: %v", err))
	}

	var req *qixing.QiXingRequestBo
	if err = json.Unmarshal(bodyBytes, &req); err != nil {
		log.Errorf("qixing notify bodyBytes err ip:%s,error:%v,body:%s", ip, err, string(bodyBytes))
		return srv.ResponseErr(ctx, fmt.Sprintf("json unmarshal bodyBytes error: %v", err))
	}

	if err = req.Validate(); err != nil {
		log.Errorf("qixing notify req validate err ip:%s,error:%v,body:%s", ip, err, string(bodyBytes))
		return srv.ResponseErr(ctx, fmt.Sprintf("validate req error: %v", err))
	}

	// 加密校验串，(生成规则：MD5(content+公钥))
	if srv.bc.Tripartite.QiXing.AppKey == "" {
		return srv.ResponseErr(ctx, "qixing appKey is empty")
	}

	sign := helper.Md5(req.Content + srv.bc.Tripartite.QiXing.AppKey)
	if sign != req.Ciphertext {
		log.Errorf("qixing notify sign err ip:%s,error:%v,body:%s", ip, err, string(bodyBytes))
		return srv.ResponseErr(ctx, "verify sign error")
	}

	wxNotifyDataStr, err := base64.StdEncoding.DecodeString(req.Content)
	if err != nil {
		log.Errorf("qixing notify wxNotifyDataStr err ip:%s,error:%v,body:%s", ip, err, string(bodyBytes))
		return srv.ResponseErr(ctx, fmt.Sprintf("base64 decode req content error: %v", err))
	}

	var wxNotifyData *bo.WechatVoucherNotifyBo
	if err = json.Unmarshal(wxNotifyDataStr, &wxNotifyData); err != nil {
		log.Errorf("qixing notify wxNotifyData err ip:%s,error:%v,body:%s", ip, err, string(bodyBytes))
		return srv.ResponseErr(ctx, fmt.Sprintf("json unmarshal wxNotifyData error: %v", err))
	}

	if err = wxNotifyData.Validate(); err != nil {
		log.Errorf("qixing notify wxNotifyData validate err ip:%s,error:%v,body:%s", ip, err, string(bodyBytes))
		return srv.ResponseErr(ctx, fmt.Sprintf("validate wxNotifyData error: %v", err))
	}

	err = srv.multiBiz.Notify(ctx, ip, "qixing_"+wxNotifyData.PlainText.StockCreatorMchid, wxNotifyData)
	if err != nil {
		log.Errorf("qixing notify run err ip:%s,error:%v,body:%s", ip, err, string(bodyBytes))
		return srv.ResponseErr(ctx, err.Error())
	}

	return srv.ResponseOK(ctx)
}

func (this *TripartiteService) ResponseOK(ctx http.Context) error {
	return ctx.JSON(http2.StatusOK, &qixing.QiXingResponse{
		Msg: "SUCCESS",
	})
}

func (this *TripartiteService) ResponseErr(ctx http.Context, msg string) error {
	return ctx.JSON(http2.StatusOK, &qixing.QiXingResponse{
		Msg: msg,
	})
}
