package camel_oil

import (
	"context"
	"errors"
	"fmt"
	v1 "kami/api/camel_oil/v1"
	"kami/internal/consts"
	"kami/internal/dao"
	"kami/internal/model/do"
	"kami/internal/model/entity"
	"kami/utility/config"

	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/net/gclient"
	"github.com/gogf/gf/v2/os/glog"
)

// ====================================================================================
// 订单回调逻辑
// ====================================================================================

// updateCallbackResult 更新回调结果（内部方法）
func (s *sCamelOil) updateCallbackResult(ctx context.Context, order *entity.V1CamelOilOrder, success bool, historyDesc string) error {
	m := dao.V1CamelOilOrder.Ctx(ctx).DB(config.GetDatabaseV1())

	if success {
		// 回调成功
		_, err := m.Where(dao.V1CamelOilOrder.Columns().Id, order.Id).Update(&do.V1CamelOilOrder{
			NotifyStatus: consts.CamelOilCallbackStatusSuccess,
			NotifyCount:  order.NotifyCount + 1,
		})

		if err != nil {
			return gerror.Wrap(err, "更新回调成功状态失败")
		}

		_ = s.RecordOrderHistory(ctx, order.OrderNo, consts.CamelOilOrderChangeTypeCallbackSuccess, "", historyDesc)
		return nil
	}
	// 回调失败
	notifyCount := order.NotifyCount + 1
	notifyStatus := consts.CamelOilCallbackStatusPending
	if notifyCount >= consts.CamelOilMaxCallbackRetry {
		notifyStatus = consts.CamelOilCallbackStatusFailed
	}

	_, err := m.Where(dao.V1CamelOilOrder.Columns().Id, order.Id).Update(&do.V1CamelOilOrder{
		NotifyStatus: notifyStatus,
		NotifyCount:  notifyCount,
	})

	if err != nil {
		return gerror.Wrap(err, "更新回调失败状态失败")
	}

	_ = s.RecordOrderHistory(ctx, order.OrderNo, consts.CamelOilOrderChangeTypeCallbackFail, "", historyDesc)

	return nil
}

// TriggerOrderCallback 触发订单回调
func (s *sCamelOil) TriggerOrderCallback(ctx context.Context, req *v1.OrderCallbackReq) (res *v1.OrderCallbackRes, err error) {
	// 1. 查询订单信息
	var order *entity.V1CamelOilOrder
	err = dao.V1CamelOilOrder.Ctx(ctx).DB(config.GetDatabaseV1()).
		Where(dao.V1CamelOilOrder.Columns().OrderNo, req.OrderNo).
		Scan(&order)

	if err != nil {
		glog.Error(ctx, "查询订单信息失败", err)
		return nil, err
	}

	if order == nil {
		return nil, gerror.New("订单不存在")
	}

	// 2. 检查订单状态
	if order.PayStatus != int(consts.CamelOilPaymentStatusPaid) {
		return &v1.OrderCallbackRes{
			Success: false,
			Message: "订单未支付，无法回调",
		}, nil
	}

	// 3. 执行回调
	err = s.executeCallback(ctx, order)
	// 4. 更新回调结果
	success := err == nil
	desc := "手动触发回调成功"
	if err != nil {
		desc = "回调失败" + err.Error()
	}
	_ = s.updateCallbackResult(ctx, order, success, desc)

	return &v1.OrderCallbackRes{
		Success: success,
		Message: map[bool]string{true: "回调成功", false: "回调失败"}[success],
	}, nil
}

// executeCallback 执行回调（内部方法）
func (s *sCamelOil) executeCallback(ctx context.Context, order *entity.V1CamelOilOrder) (err error) {
	// 查询订单信息
	var orderInfo *entity.V1OrderInfo
	if err = dao.V1OrderInfo.Ctx(ctx).DB(config.GetDatabaseV1()).Where(dao.V1OrderInfo.Columns().BankOrderId, order.MerchantOrderId).Scan(&orderInfo); err != nil || orderInfo == nil || orderInfo.Id == 0 {
		glog.Error(ctx, "查询订单失败", g.Map{"userOrderId": order.MerchantOrderId, "err": err})
		return errors.New("订单不存在")
	}
	var merchantInfo *entity.V1MerchantInfo
	if err = dao.V1MerchantInfo.Ctx(ctx).DB(config.GetDatabaseV1()).Where(dao.V1MerchantInfo.Columns().MerchantUid, orderInfo.MerchantUid).Scan(&merchantInfo); err != nil || merchantInfo == nil || merchantInfo.Id == 0 {
		glog.Error(ctx, "查询商户信息失败", g.Map{"merchantId": orderInfo.MerchantUid, "err": err})
		return errors.New("商户不存在")
	}
	// 发送 HTTP 回调请求
	_, err = gclient.New().Get(ctx, "http://kami_gateway:12309/myself/notify", g.Map{
		"orderNo":    order.OrderNo,
		"orderPrice": order.Amount,
		"factPrice":  order.Amount,
		"orderTime":  order.CreatedAt,
		"trxNo":      order.OrderNo,
		"payKey":     merchantInfo.MerchantKey,
		"statusCode": "1",
		"failReason": "无",
	})
	return err
}

// ProcessPendingCallbacks 处理待回调订单（定时任务使用）
func (s *sCamelOil) ProcessPendingCallbacks(ctx context.Context) error {
	// 查询需要回调的订单（仅查询已绑定到 Token 的订单）
	var orders []*entity.V1CamelOilOrder
	err := dao.V1CamelOilOrder.Ctx(ctx).DB(config.GetDatabaseV1()).
		InnerJoin(dao.V1CamelOilCardBinding.Table(), fmt.Sprintf("%s.%s = %s.%s",
			dao.V1CamelOilOrder.Table(), dao.V1CamelOilOrder.Columns().Id,
			dao.V1CamelOilCardBinding.Table(), dao.V1CamelOilCardBinding.Columns().OrderId)).
		Where(dao.V1CamelOilOrder.Columns().Status, consts.CamelOilOrderStatusProcessing).
		Where(dao.V1CamelOilOrder.Columns().PayStatus, consts.CamelOilPaymentStatusPaid).
		Where(dao.V1CamelOilOrder.Columns().NotifyStatus, consts.CamelOilCallbackStatusPending).
		WhereLTE(dao.V1CamelOilOrder.Columns().NotifyCount, consts.CamelOilMaxCallbackRetry).
		Fields(dao.V1CamelOilOrder.Table() + ".*").
		Distinct().
		Limit(50).
		Scan(&orders)

	if err != nil {
		glog.Error(ctx, "查询待回调订单失败", err)
		return err
	}

	if len(orders) == 0 {
		return nil
	}

	// 逐个处理回调
	successCount := 0
	for _, order := range orders {
		err = s.executeCallback(ctx, order)
		if err != nil {
			// 回调失败
			_ = s.updateCallbackResult(ctx, order, false, fmt.Sprintf("自动回调失败 %s", err.Error()))
			glog.Error(ctx, "订单回调处理失败", err)
			continue
		}
		// 回调成功
		_ = s.updateCallbackResult(ctx, order, true, "自动回调成功")
		successCount++
		glog.Info(ctx, "订单回调处理完成", g.Map{
			"total":   len(orders),
			"success": successCount,
			"failed":  len(orders) - successCount,
		})
		return nil
	}
	return nil
}
