package com.ruoyi.app.pay;

import com.ruoyi.app.order.dto.OrderPushBodyDto;
import com.ruoyi.app.order.DeliveryOrderNotificationService;
import com.ruoyi.app.order.MerchantNotificationRouter;
import com.ruoyi.app.utils.PayPush;
import com.ruoyi.app.utils.event.PushEventService;
import com.ruoyi.common.utils.LocaleUtils;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.system.domain.InfoUser;
import com.ruoyi.system.domain.PosOrder;
import com.ruoyi.system.service.IInfoUserService;
import com.ruoyi.system.utils.OrderLogHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionSynchronization;

import java.util.Locale;
import org.springframework.transaction.support.TransactionSynchronizationManager;

/** Executes the existing one-time order log and push side effects after LINE payment capture. */
@Service
public class LinePayOrderNotificationService {
    private static final Logger log = LoggerFactory.getLogger(LinePayOrderNotificationService.class);

    private final IInfoUserService infoUserService;
    private final PushEventService pushEventService;
    private final OrderLogHelper orderLogHelper;
    private final DeliveryOrderNotificationService deliveryOrderNotificationService;
    private final MerchantNotificationRouter merchantNotificationRouter;

    public LinePayOrderNotificationService(IInfoUserService infoUserService,
                                           PushEventService pushEventService,
                                           OrderLogHelper orderLogHelper,
                                           DeliveryOrderNotificationService deliveryOrderNotificationService,
                                           MerchantNotificationRouter merchantNotificationRouter) {
        this.infoUserService = infoUserService;
        this.pushEventService = pushEventService;
        this.orderLogHelper = orderLogHelper;
        this.deliveryOrderNotificationService = deliveryOrderNotificationService;
        this.merchantNotificationRouter = merchantNotificationRouter;
    }

    public void paymentCaptured(PosOrder order) {
        orderLogHelper.logSync(String.valueOf(order.getDdId()), 0, null, "system",
                "LINE Pay payment captured");
        runAfterCommit(() -> pushPaymentSuccess(order));
    }

    private void pushPaymentSuccess(PosOrder order) {
        try {
            String ddId = String.valueOf(order.getDdId());
            String body = OrderPushBodyDto.getJson(ddId, String.valueOf(order.getState()), 0);
            InfoUser user = order.getUserId() == null ? null : infoUserService.getById(order.getUserId());
            if (user != null) {
                // 推送常在异步线程执行（confirm 回调投递 linePayTaskExecutor），无请求级 locale，
                // 必须按收件人用户语言解析，否则回落 JVM 默认语言（线上为英文）
                Locale userLocale = LocaleUtils.getUserLocale(user.getUserId());
                String title = MessageUtils.message("no.message.push.message", userLocale);
                String content = MessageUtils.message("no.message.push.payment.success", userLocale);
                new PayPush().apppush(user.getCid(), title, content, body);
                pushEventService.PublisherEvent(user.getUserId(), title, content, body);
            }
            if (Long.valueOf(0L).equals(order.getType())) {
                deliveryOrderNotificationService.notifyOrderAvailable(order);
            } else {
                merchantNotificationRouter.sendStoreNotification(order.getMdId(), order.getShId(),
                        "no.message.push.message", "no.message.push.new.order", body, ddId);
            }
        } catch (Exception exception) {
            log.error("LINE Pay payment success push failed, ddId={}", order.getDdId(), exception);
        }
    }

    private static void runAfterCommit(Runnable action) {
        if (!TransactionSynchronizationManager.isSynchronizationActive()) {
            action.run();
            return;
        }
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
            @Override
            public void afterCommit() {
                action.run();
            }
        });
    }
}
