package service

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

type NotifyService struct {
	WechatBiz  *biz.WechatBiz
	VoucherBiz *biz.VoucherBiz
}

func NewNotifyService(wechatBiz *biz.WechatBiz, VoucherBiz *biz.VoucherBiz) *NotifyService {
	return &NotifyService{WechatBiz: wechatBiz, VoucherBiz: VoucherBiz}
}

// Notify https://pay.weixin.qq.com/doc/v3/merchant/4012285250
func (srv *NotifyService) Notify(ctx http.Context) error {

	mchId := ctx.Vars().Get("mch_id")
	if mchId == "" {
		log.Errorf("微信回调通知，mchId参数不能为空")
		return ctx.JSON(http2.StatusNetworkAuthenticationRequired, map[string]string{
			"code":    "FAIL",
			"message": "微信回调通知，mchId参数不能为空",
		})
	}

	headers := ctx.Request().Header
	if headers == nil {
		log.Errorf("微信回调通知[%s]，headers参数不能为空", mchId)
		return ctx.JSON(http2.StatusNetworkAuthenticationRequired, map[string]string{
			"code":    "FAIL",
			"message": "微信回调通知，headers参数不能为空",
		})
	}

	bodyBytes, err := io.ReadAll(ctx.Request().Body)
	if err != nil {
		log.Errorf("微信回调通知[%s]，读取响应体失败: %v", mchId, err)
		return fmt.Errorf("读取响应体失败: %w", err)
	}

	if len(bodyBytes) == 0 {
		log.Errorf("微信回调通知[%s]，响应体不能为空", mchId)
		return ctx.JSON(http2.StatusNetworkAuthenticationRequired, map[string]string{
			"code":    "FAIL",
			"message": "微信回调通知，响应体不能为空",
		})
	}

	bizData, err := srv.WechatBiz.CallBack(ctx, mchId, &headers, bodyBytes)
	if err != nil {
		headerJson, _ := json.Marshal(headers)
		log.Errorf("微信回调通知[%s],callBack处理失败:%s\nheaders:%s\nbody:%s", mchId, err.Error(), headerJson, string(bodyBytes))
		return ctx.JSON(http2.StatusNetworkAuthenticationRequired, map[string]string{
			"code":    "FAIL",
			"message": err.Error(),
		})
	}

	ip := helper.GetClientIP(ctx)

	if err = srv.VoucherBiz.WechatNotifyConsumer(ctx, ip, bizData); err != nil {
		headerJson, _ := json.Marshal(headers)
		log.Errorf("微信回调通知[%s],consumer处理失败:%s\nheaders:%s\nbody:%s\n解析数据:%+v", mchId, err.Error(), headerJson, string(bodyBytes), bizData)

		if errors.Is(err, gorm.ErrRecordNotFound) {
			return ctx.JSON(http2.StatusOK, nil)
		}

		return ctx.JSON(http2.StatusBadRequest, map[string]string{
			"code":    "FAIL",
			"message": err.Error(),
		})
	}

	return ctx.JSON(http2.StatusOK, nil)
}

// NotifyMock 模拟微信回调通知，用于测试
func (srv *NotifyService) NotifyMock(ctx http.Context) error {

	bodyBytes, err := io.ReadAll(ctx.Request().Body)
	if err != nil {
		log.Errorf("微信回调通知，读取响应体失败: %v", err)
		return fmt.Errorf("读取响应体失败: %w", err)
	}

	if len(bodyBytes) == 0 {
		log.Errorf("微信回调通知，响应体不能为空")
		return ctx.JSON(http2.StatusOK, map[string]string{
			"code":    "FAIL",
			"message": "微信回调通知，响应体不能为空",
		})
	}

	var bizData *bo.WechatVoucherNotifyBo
	err = json.Unmarshal(bodyBytes, &bizData)
	if err != nil {
		log.Errorf("微信回调通知，解析响应体失败: %v", err)
		return ctx.JSON(http2.StatusOK, map[string]string{
			"code":    "FAIL",
			"message": "微信回调通知，解析响应体失败",
		})
	}

	ip := helper.GetClientIP(ctx)

	if err = srv.VoucherBiz.WechatNotifyConsumer(ctx, ip, bizData); err != nil {
		log.Errorf("微信回调通知，consumer处理失败:%s\nbody:%s\n解析数据:%+v", err.Error(), string(bodyBytes), bizData)

		if errors.Is(err, gorm.ErrRecordNotFound) {
			return ctx.JSON(http2.StatusOK, nil)
		}

		return ctx.JSON(http2.StatusOK, map[string]string{
			"code":    "FAIL",
			"message": err.Error(),
		})
	}

	return ctx.JSON(http2.StatusOK, nil)
}
