package com.jeesharp.business.modules.food.sync;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.jeesharp.business.modules.food.entity.FoodBookingOrder;
import com.jeesharp.business.modules.food.event.FoodBookingDualWriteEvent;
import com.jeesharp.business.modules.food.service.FoodBookingOrderService;
import com.jeesharp.business.modules.food.vo.FoodBookingResultVO;
import com.jeesharp.business.modules.trade.api.TradeOrderFacadeApi;
import com.jeesharp.business.modules.trade.dto.TradeOrderCreateDTO;
import com.jeesharp.business.modules.trade.dto.TradeOrderLineCreateDTO;
import com.jeesharp.business.modules.trade.enums.TradeBizTypeEnum;
import com.jeesharp.business.modules.trade.enums.TradeOrderStatusEnum;
import com.jeesharp.business.modules.trade.vo.TradeOrderInfoVO;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
import org.springframework.transaction.event.TransactionPhase;
import org.springframework.transaction.event.TransactionalEventListener;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Collections;

/**
 * 美食预订与统一交易订单双写监听器（事件补偿路径）。
 * <p>主路径已由 {@link com.jeesharp.business.modules.food.application.FoodBookingOrderApplicationService} 同步。</p>
 *
 * @author jeesharp
 * @since 2026-05-08
 */
@Slf4j
@Component
@AllArgsConstructor
@ConditionalOnProperty(name = "jeesharp.trade.dual-write.food-enabled", havingValue = "true")
public class FoodTradeDualWriteListener {

    private final TradeOrderFacadeApi tradeOrderFacadeApi;
    private final FoodBookingOrderService foodBookingOrderService;

    @TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT)
    public void onFoodBookingDualWrite(FoodBookingDualWriteEvent event) {
        FoodBookingOrder current = foodBookingOrderService.get(event.getFoodOrderId());
        if (current == null) {
            log.warn("Food dual-write: food order missing id={}", event.getFoodOrderId());
            return;
        }
        if (StrUtil.isNotBlank(current.getUnifiedOrderId())) {
            log.info(
                "Food dual-write skipped (unified_order_id already set), foodOrderId={}, unifiedOrderId={}",
                event.getFoodOrderId(),
                current.getUnifiedOrderId()
            );
            return;
        }
        BigDecimal total = event.getTotalAmount() == null ? BigDecimal.ZERO : event.getTotalAmount();

        TradeOrderCreateDTO dto = new TradeOrderCreateDTO();
        dto.setMemberId(event.getMemberId());
        dto.setBizType(TradeBizTypeEnum.FOOD.getValue());
        dto.setTitle(event.getTitle());
        dto.setTotalAmount(total);
        dto.setDiscountAmount(BigDecimal.ZERO);
        dto.setPayAmount(total);
        dto.setVerticalOrderId(event.getFoodOrderId());
        dto.setExtJson("{\"dualWriteSource\":\"FOOD_M5_EVENT\"}");

        TradeOrderLineCreateDTO line = new TradeOrderLineCreateDTO();
        line.setLineNo(1);
        line.setItemTitle(event.getTitle());
        line.setSkuRef(null);
        line.setResourceRef(event.getPackageId());
        line.setQuantity(event.getQuantity());
        line.setUnitPrice(total.divide(BigDecimal.valueOf(event.getQuantity()), 2, RoundingMode.HALF_UP));
        line.setLineAmount(total);
        dto.setLines(Collections.singletonList(line));

        String createdId = tradeOrderFacadeApi.createPendingPayOrder(dto);
        tradeOrderFacadeApi.markPaid(createdId, "FOOD-" + event.getFoodOrderId(), "RESERVE");

        FoodBookingOrder order = foodBookingOrderService.get(event.getFoodOrderId());
        if (order == null) {
            log.warn("Food dual-write: food order missing after trade create id={}", event.getFoodOrderId());
            return;
        }
        order.setUnifiedOrderId(createdId);
        foodBookingOrderService.updateOrder(order);

        FoodBookingResultVO payload = foodBookingOrderService.getBookingResult(order.getId());
        if (payload != null) {
            payload.setUnifiedOrderId(createdId);
            order.setResultPayloadJson(JSONUtil.toJsonStr(payload));
            foodBookingOrderService.updateOrder(order);
        }
    }
}
