package card_apple_order

import (
	"context"
	"github.com/gogf/gf/v2/net/gtrace"
	"github.com/gogf/gf/v2/os/gtime"
	"go.opentelemetry.io/otel/trace"
	"kami/internal/consts"
	"kami/internal/dao"
	"kami/internal/model"
	"kami/internal/model/entity"
	"kami/utility/cache"
	"kami/utility/config"
	"kami/utility/pool"
	"sync"
	"time"

	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/glog"
)

// CronCallbackPendingOrders 定时任务：回调处于失败和成功状态的订单
func (h *sAppleOrder) CronCallbackPendingOrders(ctx context.Context) error {
	// 查询需要回调的订单（失败和成功状态）
	var orders []*entity.V1CardAppleRechargeInfo
	err := dao.V1CardAppleRechargeInfo.Ctx(ctx).DB(config.GetDatabaseV1()).
		WhereIn(dao.V1CardAppleRechargeInfo.Columns().Status, g.Slice{
			consts.AppleRechargeOrderFail,            // 充值失败
			consts.AppleRechargeOrderSuccess,         // 充值成功
			consts.AppleRechargeOrderAmountDifferent, // 金额不符
		}).
		WhereNot(dao.V1CardAppleRechargeInfo.Columns().NotifyStatus, consts.CardAppleNotifyStatusSuccess). // 只回调未成功的
		WhereLT(dao.V1CardAppleRechargeInfo.Columns().CallbackCount, consts.AppleOrderMaxCallbackCount).   // 未达到最大回调次数
		Limit(50).                                                                                         // 每次处理50个订单
		Scan(&orders)

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

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

	tracer := gtrace.NewTracer("sAppleOrder.CronCallbackPendingOrders")
	ctx, span := tracer.Start(ctx, "CronCallbackPendingOrders", trace.WithNewRoot(), trace.WithLinks(trace.LinkFromContext(ctx)))
	defer span.End()

	// 逐个处理订单回调
	for _, order := range orders {
		// 执行回调
		_ = h.CallBackOrderToUpstream(ctx, order.OrderNo)
	}
	return nil
}

// CronFailedScheduleTask 定时任务：回调处于失败和成功状态的订单
func (h *sAppleOrder) CronFailedScheduleTask(ctx context.Context) error {
	tracer := gtrace.NewTracer("sAppleOrder.CronFailedScheduleTask")
	ctx, span := tracer.Start(ctx, "CronFailedScheduleTask", trace.WithNewRoot(), trace.WithLinks(trace.LinkFromContext(ctx)))
	defer span.End()
	var orders []*entity.V1CardAppleRechargeInfo
	_ = dao.V1CardAppleRechargeInfo.Ctx(ctx).DB(config.GetDatabaseV1()).
		Where(dao.V1CardAppleRechargeInfo.Columns().Status, consts.AppleRechargeOrderProcessing). // 只回调未成功的
		WhereLT(dao.V1CardAppleRechargeInfo.Columns().UpdatedAt, gtime.Now().Add(-gtime.M)).
		Scan(&orders)
	for _, order := range orders {
		if err := h.AddHistory(ctx, &model.AppleCardRechargeHistoryInput{
			RechargeId:  int(order.Id),
			OrderNo:     order.OrderNo,
			AccountID:   order.AccountId,
			AccountName: order.AccountName,
			Operation:   consts.AppleRechargeOperationTimeout,
			Remark:      "订单调度超时，重新调度",
		}, nil); err != nil {
			glog.Error(ctx, "添加订单操作记录失败:", err)
		}
		_ = h.ModifyOrderStatus(ctx, order.OrderNo, consts.AppleRechargeOrderWaiting, "订单调度超时，重新调度", nil)
	}
	return nil
}

// CronProcessOrderWithPush 处理订单：根据订单类型判断是立即进行核销处理还是创建定时任务异步处理
// 参数说明：
//   - orderEntity: 待处理的订单信息
//   - accountInfo: 分配的苹果账号信息
//   - immediate: 是否立即处理（true: 立即核销，false: 异步定时处理）
func (h *sAppleOrder) CronProcessOrderWithPush(ctx context.Context) (err error) {
	orderEntities, _ := h.GetAccordingOrders(ctx)
	if len(orderEntities) == 0 {
		return
	}
	poolClient := pool.New(pool.AppleOrderProcessPushPool, 20)

	wg := sync.WaitGroup{}
	for _, orderInfo := range orderEntities {
		wg.Add(1)
		_ = poolClient.Add(ctx, func(ctx2 context.Context) {
			wg.Done()
			tracer2 := gtrace.NewTracer("sAppleOrder.CronProcessOrderWithPushTask")
			ctx2, span2 := tracer2.Start(ctx2, "CronProcessOrderWithPushTask", trace.WithNewRoot(), trace.WithLinks(trace.LinkFromContext(ctx)))
			defer span2.End()
			orderLock, _ := cache.NewCache().Get(ctx2, cache.PrefixAppleOrder.Key(orderInfo.OrderNo))
			if orderLock != nil && !orderLock.IsNil() {
				glog.Warning(ctx2, "订单正在处理中", orderInfo.OrderNo)
				return
			}
			_ = cache.NewCache().Set(ctx2, cache.PrefixAppleOrder.Key(orderInfo.OrderNo), 1, time.Minute)
			defer func() {
				_, _ = cache.NewCache().Remove(ctx2, cache.PrefixAppleOrder.Key(orderInfo.OrderNo))
			}()

			err = h.processOrderWithAccount(ctx2, orderInfo)
			if err != nil {
				glog.Error(ctx2, "处理订单失败", err)
			}
		})
	}
	wg.Wait()
	return
}
