package pay

import (
	"context"
	"sim-server/app/main/api/internal/svc"
	"sim-server/pkg/lzkit/lzUtils"
	"net/http"
	"strconv"
	"time"

	"github.com/zeromicro/go-zero/core/logx"
)

type YunYinSignPayCallbackLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewYunYinSignPayCallbackLogic(ctx context.Context, svcCtx *svc.ServiceContext) *YunYinSignPayCallbackLogic {
	return &YunYinSignPayCallbackLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

// YunYinSignPayCallback 云印签支付回调处理
func (l *YunYinSignPayCallbackLogic) YunYinSignPayCallback(w http.ResponseWriter, r *http.Request) error {
	logx.Infof("[云印签回调] 收到回调请求，Method: %s, URL: %s, RemoteAddr: %s", r.Method, r.URL.String(), r.RemoteAddr)
	logx.Infof("[云印签回调] 请求Header，Content-Type: %s, User-Agent: %s", r.Header.Get("Content-Type"), r.Header.Get("User-Agent"))

	// 检查云印签支付服务是否启用
	if l.svcCtx.YunYinSignPayService == nil {
		logx.Errorf("[云印签回调] 云印签支付服务未启用")
		w.WriteHeader(http.StatusOK)
		w.Write([]byte("success"))
		return nil
	}

	// 解析表单数据
	logx.Infof("[云印签回调] 开始解析表单数据")
	if err := r.ParseForm(); err != nil {
		logx.Errorf("[云印签回调] 解析表单数据失败: %v", err)
		w.WriteHeader(http.StatusOK)
		w.Write([]byte("success"))
		return nil
	}
	logx.Infof("[云印签回调] 表单数据解析成功，Form参数数量: %d", len(r.Form))

	// 获取回调参数
	tradeState := r.FormValue("tradeState")
	orderType := r.FormValue("orderType")
	payOrderNo := r.FormValue("payOrderNo")
	payAmount := r.FormValue("payAmount")
	flowId := r.FormValue("flowId")
	sourceOrderCode := r.FormValue("sourceOrderCode")
	channelOrderNo := r.FormValue("channelOrderNo")
	paySuccessTime := r.FormValue("paySuccessTime")

	// 记录所有回调参数
	logx.Infof("[云印签回调] 回调参数详情:")
	logx.Infof("[云印签回调]   - tradeState: %s", tradeState)
	logx.Infof("[云印签回调]   - orderType: %s", orderType)
	logx.Infof("[云印签回调]   - payOrderNo: %s", payOrderNo)
	logx.Infof("[云印签回调]   - payAmount: %s", payAmount)
	logx.Infof("[云印签回调]   - flowId: %s", flowId)
	logx.Infof("[云印签回调]   - sourceOrderCode: %s", sourceOrderCode)
	logx.Infof("[云印签回调]   - channelOrderNo: %s", channelOrderNo)
	logx.Infof("[云印签回调]   - paySuccessTime: %s", paySuccessTime)

	// 记录回调日志
	logx.Infof("[云印签回调] 回调通知摘要，订单号: %s, 支付状态: %s, 订单类型: %s, 支付单号: %s, 金额: %s, 流程ID: %s",
		sourceOrderCode, tradeState, orderType, payOrderNo, payAmount, flowId)

	// 只处理付款通知（orderType == "pay"）
	logx.Infof("[云印签回调] 检查订单类型，orderType: %s", orderType)
	if orderType != "pay" {
		logx.Infof("[云印签回调] 非付款通知，跳过处理，订单类型: %s, 订单号: %s", orderType, sourceOrderCode)
		w.WriteHeader(http.StatusOK)
		w.Write([]byte("success"))
		return nil
	}
	logx.Infof("[云印签回调] 确认为付款通知，继续处理")

	// 如果没有 sourceOrderCode，无法关联订单，直接返回成功
	if sourceOrderCode == "" {
		logx.Errorf("[云印签回调] 缺少 sourceOrderCode 参数，无法关联订单")
		w.WriteHeader(http.StatusOK)
		w.Write([]byte("success"))
		return nil
	}
	logx.Infof("[云印签回调] sourceOrderCode 存在，订单号: %s", sourceOrderCode)

	// 根据 sourceOrderCode 查找订单
	logx.Infof("[云印签回调] 开始查找订单，订单号: %s", sourceOrderCode)
	order, findOrderErr := l.svcCtx.OrderModel.FindOneByOrderNo(l.ctx, sourceOrderCode)
	if findOrderErr != nil {
		logx.Errorf("[云印签回调] 查找订单失败，订单号: %s, 错误: %v", sourceOrderCode, findOrderErr)
		w.WriteHeader(http.StatusOK)
		w.Write([]byte("success"))
		return nil
	}
	logx.Infof("[云印签回调] 订单查找成功，订单号: %s, 订单ID: %s, 订单状态: %s, 订单金额: %.2f, 支付平台: %s",
		sourceOrderCode, order.Id, order.Status, order.Amount, order.PaymentPlatform)

	// 幂等性检查：如果订单已经不是 pending 状态，说明已经处理过，直接返回成功
	logx.Infof("[云印签回调] 幂等性检查，订单状态: %s", order.Status)
	if order.Status != "pending" {
		logx.Infof("[云印签回调] 订单已处理，跳过重复处理，订单号: %s, 当前状态: %s", sourceOrderCode, order.Status)
		w.WriteHeader(http.StatusOK)
		w.Write([]byte("success"))
		return nil
	}
	logx.Infof("[云印签回调] 订单状态为pending，继续处理")

	// 验证支付状态：tradeState == "00000" 或 "success" 表示支付成功
	logx.Infof("[云印签回调] 验证支付状态，tradeState: %s", tradeState)
	isPaymentSuccess := tradeState == "00000" || tradeState == "success"
	if !isPaymentSuccess {
		logx.Infof("[云印签回调] 订单未支付成功，跳过处理，订单号: %s, 支付状态: %s", sourceOrderCode, tradeState)
		w.WriteHeader(http.StatusOK)
		w.Write([]byte("success"))
		return nil
	}
	logx.Infof("[云印签回调] 支付状态验证通过，tradeState: %s 表示支付成功", tradeState)

	// 验证金额
	logx.Infof("[云印签回调] 开始验证金额，回调金额字符串: %s, 订单金额: %.2f", payAmount, order.Amount)
	payAmountFloat, parseAmountErr := strconv.ParseFloat(payAmount, 64)
	if parseAmountErr != nil {
		logx.Errorf("[云印签回调] 金额解析失败，订单号: %s, 金额字符串: %s, 错误: %v", sourceOrderCode, payAmount, parseAmountErr)
		w.WriteHeader(http.StatusOK)
		w.Write([]byte("success"))
		return nil
	}
	logx.Infof("[云印签回调] 金额解析成功，回调金额: %.2f, 订单金额: %.2f", payAmountFloat, order.Amount)

	// 金额比较（允许小数点误差）
	amountDiff := payAmountFloat - order.Amount
	if amountDiff < 0 {
		amountDiff = -amountDiff
	}
	logx.Infof("[云印签回调] 金额差异: %.2f", amountDiff)
	if amountDiff > 0.01 { // 允许1分钱的误差
		logx.Errorf("[云印签回调] 金额不一致，订单号: %s, 订单金额: %.2f, 回调金额: %.2f, 差异: %.2f",
			sourceOrderCode, order.Amount, payAmountFloat, amountDiff)
		w.WriteHeader(http.StatusOK)
		w.Write([]byte("success"))
		return nil
	}
	logx.Infof("[云印签回调] 金额验证通过，差异在允许范围内")

	// 解析支付成功时间
	logx.Infof("[云印签回调] 开始解析支付成功时间，时间字符串: %s", paySuccessTime)
	var payTime time.Time
	if paySuccessTime != "" {
		// 尝试多种时间格式
		timeFormats := []string{
			"2006-01-02 15:04:05",
			"2006-01-02T15:04:05",
			"2006-01-02 15:04:05.000",
			"2006-01-02T15:04:05.000Z",
		}
		parsed := false
		for i, format := range timeFormats {
			if t, err := time.Parse(format, paySuccessTime); err == nil {
				payTime = t
				parsed = true
				logx.Infof("[云印签回调] 支付时间解析成功，使用格式[%d]: %s, 解析结果: %s", i, format, payTime.Format("2006-01-02 15:04:05"))
				break
			}
		}
		if !parsed {
			// 如果解析失败，使用当前时间
			payTime = time.Now()
			logx.Infof("[云印签回调] 支付时间解析失败，使用当前时间，订单号: %s, 时间字符串: %s, 当前时间: %s",
				sourceOrderCode, paySuccessTime, payTime.Format("2006-01-02 15:04:05"))
		}
	} else {
		payTime = time.Now()
		logx.Infof("[云印签回调] 支付时间字符串为空，使用当前时间: %s", payTime.Format("2006-01-02 15:04:05"))
	}

	// 更新订单状态
	logx.Infof("[云印签回调] 开始更新订单状态，订单号: %s, 订单ID: %s, 原状态: %s, 新状态: paid, 支付时间: %s, 渠道单号: %s",
		sourceOrderCode, order.Id, order.Status, payTime.Format("2006-01-02 15:04:05"), channelOrderNo)
	order.Status = "paid"
	order.PayTime = lzUtils.TimeToNullTime(payTime)
	if channelOrderNo != "" {
		order.PlatformOrderId = lzUtils.StringToNullString(channelOrderNo)
		logx.Infof("[云印签回调] 设置渠道单号，订单号: %s, 渠道单号: %s", sourceOrderCode, channelOrderNo)
	}

	logx.Infof("[云印签回调] 调用UpdateWithVersion更新订单，订单号: %s, 订单ID: %s, Version: %d",
		sourceOrderCode, order.Id, order.Version)
	if updateErr := l.svcCtx.OrderModel.UpdateWithVersion(l.ctx, nil, order); updateErr != nil {
		logx.Errorf("[云印签回调] 更新订单状态失败，订单号: %s, 订单ID: %s, 错误: %v", sourceOrderCode, order.Id, updateErr)
		w.WriteHeader(http.StatusOK)
		w.Write([]byte("success"))
		return nil
	}
	logx.Infof("[云印签回调] 订单状态更新成功，订单号: %s, 订单ID: %s", sourceOrderCode, order.Id)

	// 更新云印签订单表的支付状态
	logx.Infof("[云印签回调] 开始查找云印签订单记录，订单ID: %s, 流程ID: %s", order.Id, flowId)
	yunyinOrder, findYunyinErr := l.svcCtx.YunyinSignPayOrderModel.FindOneByOrderId(l.ctx, order.Id)
	if findYunyinErr == nil && yunyinOrder != nil {
		logx.Infof("[云印签回调] 找到云印签订单记录，订单ID: %s, 云印签订单ID: %s, 任务ID: %s, 参与者ID: %s, 当前支付状态: %d",
			order.Id, yunyinOrder.Id, yunyinOrder.TaskId, yunyinOrder.ParticipantId, yunyinOrder.PayStatus)
		// 更新支付状态为已支付（1）
		if yunyinOrder.PayStatus != 1 {
			logx.Infof("[云印签回调] 需要更新云印签订单支付状态，订单ID: %s, 原支付状态: %d, 新支付状态: 1", order.Id, yunyinOrder.PayStatus)
			yunyinOrder.PayStatus = 1
			if _, updateYunyinErr := l.svcCtx.YunyinSignPayOrderModel.Update(l.ctx, nil, yunyinOrder); updateYunyinErr != nil {
				logx.Errorf("[云印签回调] 更新云印签订单支付状态失败，订单ID: %s, 云印签订单ID: %s, 错误: %v",
					order.Id, yunyinOrder.Id, updateYunyinErr)
			} else {
				logx.Infof("[云印签回调] 成功更新云印签订单支付状态，订单ID: %s, 云印签订单ID: %s, 支付状态: 1",
					order.Id, yunyinOrder.Id)
			}
		} else {
			logx.Infof("[云印签回调] 云印签订单支付状态已是已支付，无需更新，订单ID: %s, 支付状态: %d", order.Id, yunyinOrder.PayStatus)
		}
	} else {
		if findYunyinErr != nil {
			logx.Infof("[云印签回调] 查找云印签订单记录失败，订单ID: %s, 流程ID: %s, 错误: %v", order.Id, flowId, findYunyinErr)
		} else {
			logx.Infof("[云印签回调] 未找到对应的云印签订单记录，订单ID: %s, 流程ID: %s", order.Id, flowId)
		}
	}

	// 发送异步任务处理后续流程
	logx.Infof("[云印签回调] 开始发送异步任务，订单ID: %s", order.Id)
	if asyncErr := l.svcCtx.AsynqService.SendQueryTask(order.Id); asyncErr != nil {
		logx.Errorf("[云印签回调] 异步任务调度失败，订单ID: %s, 错误: %v", order.Id, asyncErr)
		// 不返回错误，因为订单已经更新成功
	} else {
		logx.Infof("[云印签回调] 异步任务发送成功，订单ID: %s", order.Id)
	}

	logx.Infof("[云印签回调] 回调处理完成，订单号: %s, 订单ID: %s, 支付单号: %s, 渠道单号: %s, 支付金额: %.2f",
		sourceOrderCode, order.Id, payOrderNo, channelOrderNo, payAmountFloat)

	// 返回 success，云印签要求返回纯字符串 success
	logx.Infof("[云印签回调] 返回success响应给云印签")
	w.WriteHeader(http.StatusOK)
	w.Write([]byte("success"))
	return nil
}
