package biz

import (
	"context"
	"fmt"
	"go.opentelemetry.io/otel/trace"
	"time"
	"voucher/internal/pkg/lock"
	"voucher/internal/pkg/mq"
)

func (v *VoucherBiz) PushOrderMQ(ctx context.Context, orderNo string) error {

	eventMap := v.bc.RocketMQ.EventMap["order"]
	sendOption := []mq.SendOption{
		mq.WithSendShardingKeysOption(fmt.Sprintf("%s", orderNo)),
		mq.WithOpenTelemetryOption(trace.SpanFromContext(ctx).SpanContext().TraceID().String()),
	}

	if err := v.MqSendMixRepo.SendSync(ctx, eventMap.Topic, []byte("{}"), sendOption...); err != nil {
		return fmt.Errorf("收单成功，消费队列投递失败[%v]", err)
	}

	return nil
}

func (v *VoucherBiz) PushQueryDelayMQ(ctx context.Context, orderNo string) error {

	eventMap := v.bc.RocketMQ.EventMap["query"]
	sendOption := []mq.SendOption{
		mq.WithSendShardingKeysOption(orderNo),
		mq.WithOpenTelemetryOption(trace.SpanFromContext(ctx).SpanContext().TraceID().String()),
		mq.WithSendDelayLevelOption(300),
	}

	if err := v.MqSendMixRepo.SendSync(ctx, eventMap.Topic, []byte("{}"), sendOption...); err != nil {
		return fmt.Errorf("查询入队投递失败[%v]", err)
	}

	return nil
}

func (v *VoucherBiz) PushNotifyMQ(ctx context.Context, orderNo, outRequestNo string) error {

	eventMap := v.bc.RocketMQ.EventMap["notify"]
	sendOption := []mq.SendOption{
		mq.WithSendShardingKeysOption(fmt.Sprintf("%s_%s", orderNo, outRequestNo)),
		mq.WithOpenTelemetryOption(trace.SpanFromContext(ctx).SpanContext().TraceID().String()),
	}

	if err := v.MqSendMixRepo.SendSync(ctx, eventMap.Topic, []byte("{}"), sendOption...); err != nil {
		return fmt.Errorf("notify，消费队列投递失败[%v]", err)
	}

	return nil
}

func (v *VoucherBiz) OrderConsume(ctx context.Context, orderNo string) (err error) {

	err = lock.NewMutex(v.rdb.Rdb, time.Second*30).Lock(ctx, fmt.Sprintf("order_consume_%s", orderNo), func(ctx context.Context) error {

		order, err := v.OrderRepo.GetByOrderNo(ctx, orderNo)
		if err != nil {
			return err
		}

		if order.Type.IsCmb() {

			outRequestNo, err := v.Cmb.OrderConsume(ctx, order)
			if err != nil {
				return err
			}
			return v.PushNotifyMQ(ctx, orderNo, outRequestNo)

		}

		return fmt.Errorf("订单类型错误:%s", order.Type.GetText())
	})

	return
}

func (v *VoucherBiz) NotifyConsume(ctx context.Context, orderNo, orderOutRequestNo string) (err error) {

	err = lock.NewMutex(v.rdb.Rdb, time.Second*30).Lock(ctx, fmt.Sprintf("notify_consume_%s", orderNo), func(ctx context.Context) error {

		order, err := v.OrderRepo.GetByOrderNo(ctx, orderNo)
		if err != nil {
			return err
		}

		if !order.Status.CanNotify() {
			return fmt.Errorf("订单状态错误,不能通知:%s", order.Status.GetText())
		}

		if order.Type.IsCmb() {
			return v.Cmb.NotifyConsume(ctx, order, orderOutRequestNo)
		}

		return fmt.Errorf("订单类型错误:%s", order.Type.GetText())
	})

	return
}
