package com.jeesharp.business.modules.food.application.support;

import cn.hutool.core.util.StrUtil;
import com.jeesharp.business.modules.food.dto.FoodMealOrderRefundSuccessDTO;
import com.jeesharp.business.modules.food.entity.FoodCompanyAccount;
import com.jeesharp.business.modules.food.entity.FoodCompanySubsidyUse;
import com.jeesharp.business.modules.food.entity.FoodMealOrder;
import com.jeesharp.business.modules.food.entity.FoodMealOrderItem;
import com.jeesharp.business.modules.food.service.FoodCompanyAccountLedgerService;
import com.jeesharp.business.modules.food.service.FoodCompanyAccountService;
import com.jeesharp.business.modules.food.service.FoodCompanySubsidyUseService;
import com.jeesharp.business.modules.food.service.FoodMealMenuItemService;
import com.jeesharp.business.modules.food.service.FoodMealMenuItemSpecService;
import com.jeesharp.business.modules.food.service.FoodMealOrderItemService;
import com.jeesharp.business.modules.food.service.FoodMealOrderService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.List;

/**
 * 企业团餐退款成功后的业务收尾：回滚企业账户补贴、释放库存并关单（供微信退款回调与补偿共用）。
 *
 * @author jeesharp
 * @since 2026-06-11
 */
@Slf4j
@Component
@AllArgsConstructor
public class FoodCompanyMealRefundCoordinator {

    private static final String ORDER_TYPE_COMPANY = "company";
    private static final int SUBSIDY_STATUS_REFUNDED = 3;
    private static final String ORDER_STATUS_REFUNDED = "refunded";
    private static final String ORDER_STATUS_REFUNDING = "refunding";
    private static final String ORDER_STATUS_PAID = "paid";
    private static final String PAY_STATUS_REFUNDED = "refunded";
    private static final String CHANGE_TYPE_REFUND = "REFUND";
    private static final String BIZ_TYPE_MEAL_ORDER = "MEAL_ORDER";
    private static final String SOURCE_REFUND_NOTIFY = "REFUND_NOTIFY";
    private static final BigDecimal ZERO = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);

    private final FoodMealOrderService foodMealOrderService;
    private final FoodMealOrderItemService foodMealOrderItemService;
    private final FoodMealMenuItemService foodMealMenuItemService;
    private final FoodMealMenuItemSpecService foodMealMenuItemSpecService;
    private final FoodCompanyAccountService foodCompanyAccountService;
    private final FoodCompanyAccountLedgerService foodCompanyAccountLedgerService;
    private final FoodCompanySubsidyUseService foodCompanySubsidyUseService;

    /**
     * 渠道退款 SUCCESS 后幂等关闭订单并回滚企业补贴与库存。
     */
    public void applyRefundSuccess(String orderId, BigDecimal userRefundAmount, LocalDateTime refundTime) {
        if (StrUtil.isBlank(orderId)) {
            return;
        }
        FoodMealOrder order = foodMealOrderService.get(orderId.trim());
        if (order == null || !ORDER_TYPE_COMPANY.equals(order.getOrderType())) {
            return;
        }
        if (ORDER_STATUS_REFUNDED.equals(order.getOrderStatus()) || PAY_STATUS_REFUNDED.equals(order.getPayStatus())) {
            return;
        }
        if (!ORDER_STATUS_REFUNDING.equals(order.getOrderStatus()) && !ORDER_STATUS_PAID.equals(order.getOrderStatus())) {
            return;
        }
        List<FoodMealOrderItem> items = foodMealOrderItemService.listByOrderId(order.getId());
        foodMealMenuItemService.releaseSoldQuantity(items, order.getTenantCode());
        foodMealMenuItemSpecService.releaseSoldQuantity(items, order.getTenantCode());
        BigDecimal companyRefundAmount = money(order.getCompanyPayAmount());
        if (companyRefundAmount.compareTo(ZERO) > 0) {
            FoodCompanyAccount account = foodCompanyAccountService.lockByCompanyId(order.getCompanyId(), order.getTenantCode());
            foodCompanyAccountLedgerService.refundToAvailable(account, order, companyRefundAmount, SOURCE_REFUND_NOTIFY, null);
            FoodCompanySubsidyUse use = foodCompanySubsidyUseService.getByOrderId(order.getId());
            if (use != null) {
                use.setStatus(SUBSIDY_STATUS_REFUNDED);
                use.setRefundTime(refundTime != null ? refundTime : LocalDateTime.now());
                foodCompanySubsidyUseService.updateSubsidyUse(use);
            }
        }
        BigDecimal userAmount = userRefundAmount != null ? money(userRefundAmount) : money(order.getUserPayAmount());
        order.setOrderStatus(ORDER_STATUS_REFUNDED);
        order.setPayStatus(PAY_STATUS_REFUNDED);
        order.setRefundAmount(money(companyRefundAmount.add(userAmount)));
        order.setRefundTime(refundTime != null ? refundTime : LocalDateTime.now());
        if (order.getRefundApplyTime() == null) {
            order.setRefundApplyTime(order.getRefundTime());
        }
        foodMealOrderService.updateOrder(order);
        foodMealOrderItemService.markRefunded(items, false);
        log.info("企业团餐退款收尾完成 orderId={}, orderNo={}, refundAmount={}", order.getId(), order.getOrderNo(), order.getRefundAmount());
    }

    /**
     * 兼容旧退款回调 DTO 形态。
     */
    public void applyRefundSuccess(FoodMealOrderRefundSuccessDTO dto) {
        if (dto == null) {
            return;
        }
        applyRefundSuccess(dto.getOrderId(), dto.getRefundAmount(), dto.getRefundTime());
    }

    private static BigDecimal money(BigDecimal value) {
        return value == null ? ZERO : value.setScale(2, RoundingMode.HALF_UP);
    }
}
