package cn.newfeifan.mall.module.trade.service.aftersale;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.newfeifan.mall.framework.common.pojo.PageParam;
import cn.newfeifan.mall.framework.common.pojo.PageResult;
import cn.newfeifan.mall.framework.common.util.object.BeanUtils;
import cn.newfeifan.mall.framework.common.util.object.ObjectUtils;
import cn.newfeifan.mall.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.newfeifan.mall.module.distri.controller.admin.dailybill.vo.DailyBillSaveReqVO;
import cn.newfeifan.mall.module.distri.controller.admin.ptdailybill.vo.PtDailyBillSaveReqVO;
import cn.newfeifan.mall.module.distri.controller.admin.ptprofit.vo.PtProfitSaveReqVO;
import cn.newfeifan.mall.module.distri.dal.dataobject.dailybill.DailyBillDO;
import cn.newfeifan.mall.module.distri.dal.dataobject.ptdailybill.PtDailyBillDO;
import cn.newfeifan.mall.module.distri.dal.dataobject.ptprofit.PtProfitDO;
import cn.newfeifan.mall.module.distri.enums.CaclEnum;
import cn.newfeifan.mall.module.distri.enums.IntegralEnum;
import cn.newfeifan.mall.module.distri.enums.IntegralTypeEnum;
import cn.newfeifan.mall.module.distri.service.dailybill.DailyBillService;
import cn.newfeifan.mall.module.distri.service.integral.IntegralService;
import cn.newfeifan.mall.module.distri.service.ptdailybill.PtDailyBillService;
import cn.newfeifan.mall.module.distri.service.ptprofit.PtProfitService;
import cn.newfeifan.mall.module.distri.service.ptprofitlog.PtProfitLogService;
import cn.newfeifan.mall.module.member.dal.dataobject.user.MemberUserDO;
import cn.newfeifan.mall.module.member.service.user.MemberUserService;
import cn.newfeifan.mall.module.pay.api.refund.PayRefundApi;
import cn.newfeifan.mall.module.pay.api.refund.dto.PayRefundCreateReqDTO;
import cn.newfeifan.mall.module.system.controller.admin.user.vo.user.UserShopDetailsVO;
import cn.newfeifan.mall.module.system.service.user.AdminUserService;
import cn.newfeifan.mall.module.trade.controller.admin.aftersale.vo.AfterSaleDisagreeReqVO;
import cn.newfeifan.mall.module.trade.controller.admin.aftersale.vo.AfterSalePageReqVO;
import cn.newfeifan.mall.module.trade.controller.admin.aftersale.vo.AfterSaleRefuseReqVO;
import cn.newfeifan.mall.module.trade.controller.admin.order.vo.TradeOrderPageReqVO;
import cn.newfeifan.mall.module.trade.controller.app.aftersale.vo.AppAfterSaleCreateReqVO;
import cn.newfeifan.mall.module.trade.controller.app.aftersale.vo.AppAfterSaleDeliveryReqVO;
import cn.newfeifan.mall.module.trade.convert.aftersale.AfterSaleConvert;
import cn.newfeifan.mall.module.trade.dal.dataobject.aftersale.AfterSaleDO;
import cn.newfeifan.mall.module.trade.dal.dataobject.delivery.DeliveryExpressDO;
import cn.newfeifan.mall.module.trade.dal.dataobject.order.TradeOrderDO;
import cn.newfeifan.mall.module.trade.dal.dataobject.order.TradeOrderItemDO;
import cn.newfeifan.mall.module.trade.dal.mysql.aftersale.AfterSaleMapper;
import cn.newfeifan.mall.module.trade.dal.mysql.order.TradeOrderItemMapper;
import cn.newfeifan.mall.module.trade.dal.mysql.order.TradeOrderMapper;
import cn.newfeifan.mall.module.trade.dal.redis.no.TradeNoRedisDAO;
import cn.newfeifan.mall.module.trade.enums.aftersale.AfterSaleOperateTypeEnum;
import cn.newfeifan.mall.module.trade.enums.aftersale.AfterSaleStatusEnum;
import cn.newfeifan.mall.module.trade.enums.aftersale.AfterSaleTypeEnum;
import cn.newfeifan.mall.module.trade.enums.aftersale.AfterSaleWayEnum;
import cn.newfeifan.mall.module.trade.enums.order.TradeOrderItemAfterSaleStatusEnum;
import cn.newfeifan.mall.module.trade.enums.order.TradeOrderStatusEnum;
import cn.newfeifan.mall.module.trade.enums.wxmessage.WcChatMessageTemplateIdEnum;
import cn.newfeifan.mall.module.trade.framework.aftersale.core.annotations.AfterSaleLog;
import cn.newfeifan.mall.module.trade.framework.aftersale.core.utils.AfterSaleLogUtils;
import cn.newfeifan.mall.module.trade.framework.order.config.TradeOrderProperties;
import cn.newfeifan.mall.module.trade.service.delivery.DeliveryExpressService;
import cn.newfeifan.mall.module.trade.service.order.TradeOrderQueryService;
import cn.newfeifan.mall.module.trade.service.order.TradeOrderUpdateService;
import cn.newfeifan.mall.module.trade.utils.push.JPushUtils;
import cn.newfeifan.mall.module.trade.utils.push.pojo.RequestBody;
import cn.newfeifan.mall.module.trade.utils.wechat.WcChatMessageUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.text.DecimalFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import static cn.newfeifan.mall.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.newfeifan.mall.module.trade.enums.ErrorCodeConstants.*;

/**
 * 售后订单 Service 实现类
 *
 * @author 非繁源码
 */
@Slf4j
@Service
@Validated
public class AfterSaleServiceImpl implements AfterSaleService {

    @Resource
    private TradeOrderUpdateService tradeOrderUpdateService;
    @Resource
    private TradeOrderQueryService tradeOrderQueryService;
    @Resource
    private DeliveryExpressService deliveryExpressService;

    @Resource
    private AfterSaleMapper tradeAfterSaleMapper;
    @Resource
    private TradeNoRedisDAO tradeNoRedisDAO;

    @Resource
    private PayRefundApi payRefundApi;

    @Resource
    private TradeOrderProperties tradeOrderProperties;

    @Resource
    private AdminUserService userService;

    @Resource
    private TradeOrderMapper tradeOrderMapper;
    @Resource
    private TradeOrderItemMapper tradeOrderItemMapper;
    @Resource
    private IntegralService integralService;

    @Resource
    private WcChatMessageUtils wcChatMessageUtils;
    @Resource
    private JPushUtils jPushUtils;
    @Resource
    private MemberUserService memberUserService;
    @Resource
    private PtProfitService ptProfitService;
    @Resource
    private PtProfitLogService ptProfitLogService;

    @Resource
    private DailyBillService dailyBillService;

    @Resource
    private PtDailyBillService ptDailyBillService;


    @Override
    public PageResult<AfterSaleDO> getAfterSalePage(AfterSalePageReqVO pageReqVO) {
        UserShopDetailsVO userShopDetails = userService.getUserShopDetails();
        pageReqVO.setShopId(userShopDetails.getShopId());
        pageReqVO.setMerchantId(userShopDetails.getMerId());
        return tradeAfterSaleMapper.selectPage(pageReqVO);
    }

    @Override
    public PageResult<AfterSaleDO> getAfterSalePage(Long userId, PageParam pageParam) {
        return tradeAfterSaleMapper.selectPage(userId, pageParam);
    }

    @Override
    public AfterSaleDO getAfterSale(Long userId, Long id) {
        return tradeAfterSaleMapper.selectByIdAndUserId(id, userId);
    }

    @Override
    public AfterSaleDO getAfterSale(Long id) {
        return tradeAfterSaleMapper.selectById(id);
    }

    @Override
    public AfterSaleDO getAfterSaleByOrderNo(String orderNo) {
        return tradeAfterSaleMapper.selectOne(new LambdaQueryWrapper<AfterSaleDO>().eq(AfterSaleDO::getOrderNo, orderNo));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @AfterSaleLog(operateType = AfterSaleOperateTypeEnum.MEMBER_CREATE)
    public Long createAfterSale(Long userId, AppAfterSaleCreateReqVO createReqVO) {
        // 第一步，前置校验
        TradeOrderItemDO tradeOrderItem = validateOrderItemApplicable(userId, createReqVO);

        // 第二步，存储售后订单
        AfterSaleDO afterSale = createAfterSale(createReqVO, tradeOrderItem);
        return afterSale.getId();
    }

    /**
     * 校验交易订单项是否可以申请售后
     *
     * @param userId      用户编号
     * @param createReqVO 售后创建信息
     * @return 交易订单项
     */
    private TradeOrderItemDO validateOrderItemApplicable(Long userId, AppAfterSaleCreateReqVO createReqVO) {
        // 校验订单项存在
        TradeOrderItemDO orderItem = tradeOrderQueryService.getOrderItem(userId, createReqVO.getOrderItemId());
        if (orderItem == null) {
            throw exception(ORDER_ITEM_NOT_FOUND);
        }
        // 已申请售后，不允许再发起售后申请
        if (!TradeOrderItemAfterSaleStatusEnum.isNone(orderItem.getAfterSaleStatus())) {
            throw exception(AFTER_SALE_CREATE_FAIL_ORDER_ITEM_APPLIED);
        }
        // 申请的退款金额，不能超过商品的价格
        if (createReqVO.getRefundPrice() > orderItem.getPayIntegral()) {
            throw exception(AFTER_SALE_CREATE_FAIL_REFUND_PRICE_ERROR);
        }

        // 校验订单存在
        TradeOrderDO order = tradeOrderQueryService.getOrder(userId, orderItem.getOrderId());
        if (order == null) {
            throw exception(ORDER_NOT_FOUND);
        }
        // TODO 非繁人：超过一定时间，不允许售后
        // 已取消，无法发起售后
        if (TradeOrderStatusEnum.isCanceled(order.getStatus())) {
            throw exception(AFTER_SALE_CREATE_FAIL_ORDER_STATUS_CANCELED);
        }
        // 未支付，无法发起售后
        if (!TradeOrderStatusEnum.havePaid(order.getStatus())) {
            throw exception(AFTER_SALE_CREATE_FAIL_ORDER_STATUS_NO_PAID);
        }
        // 如果是【退货退款】的情况，需要额外校验是否发货
        if (createReqVO.getWay().equals(AfterSaleWayEnum.RETURN_AND_REFUND.getWay())
                && !TradeOrderStatusEnum.haveDelivered(order.getStatus())) {
            throw exception(AFTER_SALE_CREATE_FAIL_ORDER_STATUS_NO_DELIVERED);
        }
        return orderItem;
    }

    private AfterSaleDO createAfterSale(AppAfterSaleCreateReqVO createReqVO,
                                        TradeOrderItemDO orderItem) {
        // 创建售后单
        AfterSaleDO afterSale = AfterSaleConvert.INSTANCE.convert(createReqVO, orderItem);
        afterSale.setNo(tradeNoRedisDAO.generate(TradeNoRedisDAO.AFTER_SALE_NO_PREFIX));
        afterSale.setStatus(AfterSaleStatusEnum.APPLY.getStatus());
        // 标记是售中还是售后
        TradeOrderDO order = tradeOrderQueryService.getOrder(orderItem.getUserId(), orderItem.getOrderId());
        afterSale.setOrderNo(order.getNo()); // 记录 orderNo 订单流水，方便后续检索
        afterSale.setType(TradeOrderStatusEnum.isCompleted(order.getStatus())
                ? AfterSaleTypeEnum.AFTER_SALE.getType() : AfterSaleTypeEnum.IN_SALE.getType());
        tradeAfterSaleMapper.insert(afterSale);

        // 更新交易订单项的售后状态
        tradeOrderUpdateService.updateOrderItemWhenAfterSaleCreate(orderItem.getId(), afterSale.getId());

        // 记录售后日志
        AfterSaleLogUtils.setAfterSaleInfo(afterSale.getId(), null,
                AfterSaleStatusEnum.APPLY.getStatus());

        // TODO 发送售后消息
        return afterSale;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @AfterSaleLog(operateType = AfterSaleOperateTypeEnum.ADMIN_AGREE_APPLY)
    public void agreeAfterSale(Long userId, Long id) {
        // 校验售后单存在，并状态未审批
        AfterSaleDO afterSale = validateAfterSaleAuditable(id);

        // 更新售后单的状态
        // 情况一：退款：标记为 WAIT_REFUND 状态。后续等退款发起成功后，在标记为 COMPLETE 状态
        // 情况二：退货退款：需要等用户退货后，才能发起退款
        Integer newStatus = afterSale.getWay().equals(AfterSaleWayEnum.REFUND.getWay()) ?
                AfterSaleStatusEnum.WAIT_REFUND.getStatus() : AfterSaleStatusEnum.SELLER_AGREE.getStatus();
        updateAfterSaleStatus(afterSale.getId(), AfterSaleStatusEnum.APPLY.getStatus(), new AfterSaleDO()
                .setStatus(newStatus).setAuditUserId(userId).setAuditTime(LocalDateTime.now()));

        // 记录售后日志
        AfterSaleLogUtils.setAfterSaleInfo(afterSale.getId(), afterSale.getStatus(), newStatus);

        // TODO 发送售后消息
//        if (afterSale.getWay().equals(AfterSaleWayEnum.RETURN_AND_REFUND.getWay())) {
//             发送微信消息
//            sentWcChatMessage(afterSale, AfterSaleStatusEnum.SELLER_AGREE.getContent());
//             发送极光推送
//            sentJPush(afterSale, AfterSaleStatusEnum.SELLER_AGREE.getContent());
//        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @AfterSaleLog(operateType = AfterSaleOperateTypeEnum.ADMIN_DISAGREE_APPLY)
    public void disagreeAfterSale(Long userId, AfterSaleDisagreeReqVO auditReqVO) {
        // 校验售后单存在，并状态未审批
        AfterSaleDO afterSale = validateAfterSaleAuditable(auditReqVO.getId());

        // 更新售后单的状态
        Integer newStatus = AfterSaleStatusEnum.SELLER_DISAGREE.getStatus();
        updateAfterSaleStatus(afterSale.getId(), AfterSaleStatusEnum.APPLY.getStatus(), new AfterSaleDO()
                .setStatus(newStatus).setAuditUserId(userId).setAuditTime(LocalDateTime.now())
                .setAuditReason(auditReqVO.getAuditReason()));

        // 记录售后日志
        AfterSaleLogUtils.setAfterSaleInfo(afterSale.getId(), afterSale.getStatus(), newStatus);

        // 发送给微信用户售后消息
        sentWcChatMessage(afterSale, AfterSaleStatusEnum.SELLER_DISAGREE.getContent());

        // 发送极光推送
        sentJPush(afterSale, AfterSaleStatusEnum.SELLER_DISAGREE.getContent());

        // 更新交易订单项的售后状态为【未申请】
        tradeOrderUpdateService.updateOrderItemWhenAfterSaleCancel(afterSale.getOrderItemId());
    }

    /**
     * 校验售后单是否可审批（同意售后、拒绝售后）
     *
     * @param id 售后编号
     * @return 售后单
     */
    private AfterSaleDO validateAfterSaleAuditable(Long id) {
        AfterSaleDO afterSale = tradeAfterSaleMapper.selectById(id);
        if (afterSale == null) {
            throw exception(AFTER_SALE_NOT_FOUND);
        }
        if (ObjectUtil.notEqual(afterSale.getStatus(), AfterSaleStatusEnum.APPLY.getStatus())) {
            throw exception(AFTER_SALE_AUDIT_FAIL_STATUS_NOT_APPLY);
        }
        return afterSale;
    }

    private void updateAfterSaleStatus(Long id, Integer status, AfterSaleDO updateObj) {
        int updateCount = tradeAfterSaleMapper.updateByIdAndStatus(id, status, updateObj);
        if (updateCount == 0) {
            throw exception(AFTER_SALE_UPDATE_STATUS_FAIL);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @AfterSaleLog(operateType = AfterSaleOperateTypeEnum.MEMBER_DELIVERY)
    public void deliveryAfterSale(Long userId, AppAfterSaleDeliveryReqVO deliveryReqVO) {
        // 校验售后单存在，并状态未退货
        AfterSaleDO afterSale = tradeAfterSaleMapper.selectById(deliveryReqVO.getId());
        if (afterSale == null) {
            throw exception(AFTER_SALE_NOT_FOUND);
        }
        if (ObjectUtil.notEqual(afterSale.getStatus(), AfterSaleStatusEnum.SELLER_AGREE.getStatus())) {
            throw exception(AFTER_SALE_DELIVERY_FAIL_STATUS_NOT_SELLER_AGREE);
        }
        DeliveryExpressDO express = deliveryExpressService.validateDeliveryExpress(deliveryReqVO.getLogisticsId());

        // 更新售后单的物流信息
        updateAfterSaleStatus(afterSale.getId(), AfterSaleStatusEnum.SELLER_AGREE.getStatus(), new AfterSaleDO()
                .setStatus(AfterSaleStatusEnum.BUYER_DELIVERY.getStatus())
                .setLogisticsId(deliveryReqVO.getLogisticsId()).setLogisticsNo(deliveryReqVO.getLogisticsNo())
                .setDeliveryTime(LocalDateTime.now()));

        // 记录售后日志
        AfterSaleLogUtils.setAfterSaleInfo(afterSale.getId(), afterSale.getStatus(),
                AfterSaleStatusEnum.BUYER_DELIVERY.getStatus(),
                MapUtil.<String, Object>builder().put("deliveryName", express.getName())
                        .put("logisticsNo", deliveryReqVO.getLogisticsNo()).build());

        // TODO 发送售后消息
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @AfterSaleLog(operateType = AfterSaleOperateTypeEnum.ADMIN_AGREE_RECEIVE)
    public void receiveAfterSale(Long userId, Long id) {
        // 校验售后单存在，并状态为已退货
        AfterSaleDO afterSale = validateAfterSaleReceivable(id);

        // 更新售后单的状态
        updateAfterSaleStatus(afterSale.getId(), AfterSaleStatusEnum.BUYER_DELIVERY.getStatus(), new AfterSaleDO()
                .setStatus(AfterSaleStatusEnum.WAIT_REFUND.getStatus()).setReceiveTime(LocalDateTime.now()));

        // 记录售后日志
        AfterSaleLogUtils.setAfterSaleInfo(afterSale.getId(), afterSale.getStatus(),
                AfterSaleStatusEnum.WAIT_REFUND.getStatus());

        // TODO 发送售后消息
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @AfterSaleLog(operateType = AfterSaleOperateTypeEnum.ADMIN_DISAGREE_RECEIVE)
    public void refuseAfterSale(Long userId, AfterSaleRefuseReqVO refuseReqVO) {
        // 校验售后单存在，并状态为已退货
        AfterSaleDO afterSale = tradeAfterSaleMapper.selectById(refuseReqVO.getId());
        if (afterSale == null) {
            throw exception(AFTER_SALE_NOT_FOUND);
        }
        if (ObjectUtil.notEqual(afterSale.getStatus(), AfterSaleStatusEnum.BUYER_DELIVERY.getStatus())) {
            throw exception(AFTER_SALE_CONFIRM_FAIL_STATUS_NOT_BUYER_DELIVERY);
        }

        // 更新售后单的状态
        updateAfterSaleStatus(afterSale.getId(), AfterSaleStatusEnum.BUYER_DELIVERY.getStatus(), new AfterSaleDO()
                .setStatus(AfterSaleStatusEnum.SELLER_REFUSE.getStatus()).setReceiveTime(LocalDateTime.now())
                .setReceiveReason(refuseReqVO.getRefuseMemo()));

        // 记录售后日志
        AfterSaleLogUtils.setAfterSaleInfo(afterSale.getId(), afterSale.getStatus(),
                AfterSaleStatusEnum.SELLER_REFUSE.getStatus(),
                MapUtil.of("reason", refuseReqVO.getRefuseMemo()));

        // TODO 发送售后消息
        sentWcChatMessage(afterSale, AfterSaleStatusEnum.SELLER_REFUSE.getContent());

        // 发送极光推送
        sentJPush(afterSale, AfterSaleStatusEnum.SELLER_REFUSE.getContent());

        // 更新交易订单项的售后状态为【未申请】
        tradeOrderUpdateService.updateOrderItemWhenAfterSaleCancel(afterSale.getOrderItemId());
    }

    /**
     * 校验售后单是否可收货，即处于买家已发货
     *
     * @param id 售后编号
     * @return 售后单
     */
    private AfterSaleDO validateAfterSaleReceivable(Long id) {
        AfterSaleDO afterSale = tradeAfterSaleMapper.selectById(id);
        if (afterSale == null) {
            throw exception(AFTER_SALE_NOT_FOUND);
        }
        if (ObjectUtil.notEqual(afterSale.getStatus(), AfterSaleStatusEnum.BUYER_DELIVERY.getStatus())) {
            throw exception(AFTER_SALE_CONFIRM_FAIL_STATUS_NOT_BUYER_DELIVERY);
        }
        return afterSale;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @AfterSaleLog(operateType = AfterSaleOperateTypeEnum.ADMIN_REFUND)
    public void refundAfterSale(Long userId, String userIp, Long id) {
        // 校验售后单的状态，并状态待退款
        AfterSaleDO afterSale = tradeAfterSaleMapper.selectById(id);
        if (afterSale == null) {
            throw exception(AFTER_SALE_NOT_FOUND);
        }
        if (ObjectUtil.notEqual(afterSale.getStatus(), AfterSaleStatusEnum.WAIT_REFUND.getStatus())) {
            throw exception(AFTER_SALE_REFUND_FAIL_STATUS_NOT_WAIT_REFUND);
        }

        //退积分 add by Ben
        //1. 退购物使用的积分
        Long tradeOrderId = afterSale.getOrderId();//购物单ID
        Long orderUserId = afterSale.getUserId();
        TradeOrderDO tradeOrderDO = tradeOrderMapper.selectById(tradeOrderId);
        String tradeOrderNum = tradeOrderDO.getNo();

        //交易订单项编号
        Long orderItemId = afterSale.getOrderItemId();
        TradeOrderItemDO tradeOrderItemDO = tradeOrderItemMapper.selectById(orderItemId);
        Long payIntegral = tradeOrderItemDO.getPayIntegral();//支付积分

        //查询该订单是否有对应的日结单
        DailyBillDO dailyBill = dailyBillService.getDailyBill(afterSale.getMerchantId(), afterSale.getShopId(), tradeOrderDO.getCreateTime().toLocalDate());
        PtDailyBillDO ptDailyBill = ptDailyBillService.getPtDailyBill(tradeOrderDO.getCreateTime().toLocalDate());

        //记录退还积分
        if (payIntegral > 0) {
            TradeOrderItemDO toid = new TradeOrderItemDO();
            toid.setId(tradeOrderItemDO.getId());
            toid.setRefundIntegral(payIntegral);
            tradeOrderItemMapper.updateById(toid);

            if (tradeOrderDO.getRefundIntegral() != null) {
                tradeOrderDO.setRefundIntegral(tradeOrderDO.getRefundIntegral() + payIntegral);
            } else {
                tradeOrderDO.setRefundIntegral(payIntegral);
            }
            tradeOrderMapper.updateById(tradeOrderDO);

            //退回退款订单项,购物者支付的积分
//            integralService.updateUserIntegral(orderUserId, orderUserId, CaclEnum.ORDER_REFUND_INTEGRAL, payIntegral, 0L, tradeOrderId, tradeOrderNum);

            if (dailyBill != null) {
                //有就追加退回积分
                dailyBill.setRefundIntegral(dailyBill.getRefundIntegral() + payIntegral);
                dailyBill.setReceivedIntegral(dailyBill.getReceivedIntegral() - payIntegral);

                ptDailyBill.setRefundIntegral(ptDailyBill.getRefundIntegral() + payIntegral);
                ptDailyBill.setReceivedIntegral(ptDailyBill.getReceivedIntegral() - payIntegral);
            }
        }

//        if (dailyBill != null) {
//            //有就追加退款金额
//            dailyBill.setRefundPrice(dailyBill.getRefundPrice() + afterSale.getRefundIntegral());
//            dailyBill.setReceivedPrice(dailyBill.getReceivedPrice() - afterSale.getRefundIntegral());
//            dailyBillService.updateDailyBill(BeanUtils.toBean(dailyBill, DailyBillSaveReqVO.class));
//
//            ptDailyBill.setRefundPrice(ptDailyBill.getRefundPrice() + afterSale.getRefundIntegral());
//            ptDailyBill.setReceivedPrice(ptDailyBill.getReceivedPrice() - afterSale.getRefundIntegralTotal());
//            ptDailyBillService.updatePtDailyBill(BeanUtils.toBean(ptDailyBill, PtDailyBillSaveReqVO.class));
//        }

        //2. 减少退货物品对应的冻结积分
        Long ancestorIncreaseIntegral = tradeOrderItemDO.getAncestorIncreaseIntegral();//消费者推荐人得冻结积分
        Long freezeHighQuota = tradeOrderItemDO.getFreezeHighQuota();


        //订单退款，收回消费者获得的冻结积分
        integralService.updateUserIntegral(orderUserId, orderUserId, IntegralEnum.INTEGRAL_RECIPIENT, 0L * (-1), null,"1", 1,null);

        //20240604 推荐人（上级用户ID）
        Long ancesterUserId = tradeOrderMapper.selectAncesterByMemberUserId(orderUserId);
        //订单退款,收回消费者获得的冻结峰值
        integralService.updateIntegralFreezeHighQuota(orderUserId, orderUserId, CaclEnum.ORDER_REFUND_ORDER_PAY_FREEZE_HIGH_QUOTA, freezeHighQuota, tradeOrderId, tradeOrderNum);

        MemberUserDO user = memberUserService.getUser(orderUserId);
        // 如果用户是游客,需要撤回平台的游客收益
        if (user.getVisitor()) {
            // 获取平台的游客收益
            PtProfitDO ptProfitDO = ptProfitService.getPtProfit();
            ptProfitDO.setVisitorEarnings(ptProfitDO.getVisitorEarnings() + ancestorIncreaseIntegral);
            ptProfitDO.setPtTotalAdd(ptProfitDO.getPtTotalAdd() + ancestorIncreaseIntegral);
            ptProfitService.updatePtProfit(BeanUtils.toBean(ptProfitDO, PtProfitSaveReqVO.class));

            ptProfitLogService.addMessage(user.getId(), null, CaclEnum.ORDER_REFUND_INTEGRAL_ANCESTER, ancestorIncreaseIntegral,
                    ptProfitDO.getVisitorEarnings(), null, null, null, tradeOrderId, tradeOrderNum);
        }

        // 发起退款单。注意，需要在事务提交后，再进行发起，避免重复发起
        createPayRefund(userIp, afterSale);

        // 更新售后单的状态为【已完成】
        updateAfterSaleStatus(afterSale.getId(), AfterSaleStatusEnum.WAIT_REFUND.getStatus(), new AfterSaleDO()
                .setStatus(AfterSaleStatusEnum.COMPLETE.getStatus()).setRefundTime(LocalDateTime.now()));

        // 记录售后日志
        AfterSaleLogUtils.setAfterSaleInfo(afterSale.getId(), afterSale.getStatus(),
                AfterSaleStatusEnum.COMPLETE.getStatus());

        // 发送给微信用户售后消息
        sentWcChatMessage(afterSale, AfterSaleStatusEnum.COMPLETE.getContent());

        // 发送极光推送
        sentJPush(afterSale, AfterSaleStatusEnum.COMPLETE.getContent());

        // 更新交易订单项的售后状态为【已完成】
        tradeOrderUpdateService.updateOrderItemWhenAfterSaleSuccess(afterSale.getOrderItemId(), afterSale.getRefundIntegral().intValue());
    }

    /**
     * 发送微信消息
     *
     * @param afterSale   售后订单
     * @param afterStatus 是否同意退款
     */
    private void sentWcChatMessage(AfterSaleDO afterSale, String afterStatus) {
        List<String> params = new ArrayList<>();
        params.add(afterSale.getNo());
        params.add(afterSale.getSpuName());

        DecimalFormat df = new DecimalFormat("0.00");
        String formattedPrice = df.format((double) afterSale.getRefundIntegral() / 100);

        params.add("￥ " + formattedPrice);
        params.add(afterStatus);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        params.add(LocalDateTime.now().format(formatter));
        wcChatMessageUtils.sendWcChatMessage(afterSale.getUserId(), WcChatMessageTemplateIdEnum.AFTER_SALE_CHECK2.getTemplateId(),
                params, null, afterSale.getUserId(), afterSale.getId());
    }

    /**
     * 发送极光推送消息
     *
     * @param afterSale   售后订单
     * @param afterStatus 是否同意退款
     */
    private void sentJPush(AfterSaleDO afterSale, String afterStatus) {
        String title = WcChatMessageTemplateIdEnum.AFTER_SALE_CHECK2.getName();

        String alert = "售后订单号: " + afterSale.getNo();
        alert += "\n商品名称: " + afterSale.getSpuName();
        DecimalFormat df = new DecimalFormat("0.00");
        String formattedPrice = df.format((double) afterSale.getRefundIntegral() / 100);
        alert += "\n金额: ￥ " + formattedPrice;

        alert += "\n售后状态: " + afterStatus;
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        alert += "\n时间: " + LocalDateTime.now().format(formatter);

        List<String> userRsgIds = memberUserService.getUserRsgIds(null, afterSale.getUserId());
        if (userRsgIds != null && !userRsgIds.isEmpty()) {
            String url = jPushUtils.getUrl(title, afterSale.getUserId(), afterSale.getId());
            RequestBody requestBody = jPushUtils.getRequestBody(userRsgIds, alert, title, url);
            jPushUtils.jPush(requestBody, afterSale.getUserId(), null, afterSale.getId());
        }
    }

    private void createPayRefund(String userIp, AfterSaleDO afterSale) {
//        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {

//            @Override
//            public void afterCommit() {
        // 创建退款单
        PayRefundCreateReqDTO createReqDTO = AfterSaleConvert.INSTANCE.convert(userIp, afterSale, tradeOrderProperties)
                .setReason(StrUtil.format("退款【{}】", afterSale.getSpuName()));
        Long payRefundId = payRefundApi.createRefund(createReqDTO);
        // 更新售后单的退款单号
        tradeAfterSaleMapper.updateById(new AfterSaleDO().setId(afterSale.getId()));
//            }
//        });
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @AfterSaleLog(operateType = AfterSaleOperateTypeEnum.MEMBER_CANCEL)
    public void cancelAfterSale(Long userId, Long id) {
        // 校验售后单的状态，并状态待退款
        AfterSaleDO afterSale = tradeAfterSaleMapper.selectById(id);
        if (afterSale == null) {
            throw exception(AFTER_SALE_NOT_FOUND);
        }
        if (!ObjectUtils.equalsAny(afterSale.getStatus(), AfterSaleStatusEnum.APPLY.getStatus(),
                AfterSaleStatusEnum.SELLER_AGREE.getStatus(),
                AfterSaleStatusEnum.BUYER_DELIVERY.getStatus())) {
            throw exception(AFTER_SALE_CANCEL_FAIL_STATUS_NOT_APPLY_OR_AGREE_OR_BUYER_DELIVERY);
        }

        // 更新售后单的状态为【已取消】
        updateAfterSaleStatus(afterSale.getId(), afterSale.getStatus(), new AfterSaleDO()
                .setStatus(AfterSaleStatusEnum.BUYER_CANCEL.getStatus()));

        // 记录售后日志
        AfterSaleLogUtils.setAfterSaleInfo(afterSale.getId(), afterSale.getStatus(),
                AfterSaleStatusEnum.BUYER_CANCEL.getStatus());

        // TODO 发送售后消息

        // 更新交易订单项的售后状态为【未申请】
        tradeOrderUpdateService.updateOrderItemWhenAfterSaleCancel(afterSale.getOrderItemId());
    }

    @Override
    public Long getApplyingAfterSaleCount(Long userId, TradeOrderPageReqVO reqVO) {
        UserShopDetailsVO userShopDetails = userService.getUserShopDetails();
        reqVO.setShopId(userShopDetails.getShopId());
        reqVO.setMerchantId(userShopDetails.getMerId());
        return tradeAfterSaleMapper.selectCountByUserIdAndStatus(userId, AfterSaleStatusEnum.APPLYING_STATUSES, reqVO);
    }

    @Override
    public List<AfterSaleDO> getAfterSaleByMer(List<Long> orderIds) {
        return tradeAfterSaleMapper.selectList(new LambdaQueryWrapper<AfterSaleDO>()
                .in(AfterSaleDO::getOrderId, orderIds));
    }

    @Override
    public List<AfterSaleDO> getAfterSaleByProId(Long spuId) {
        UserShopDetailsVO userShopDetails = userService.getUserShopDetails();
        return tradeAfterSaleMapper.selectList(new LambdaQueryWrapperX<AfterSaleDO>()
                .eq(AfterSaleDO::getSpuId, spuId)
                .eqIfPresent(AfterSaleDO::getShopId, userShopDetails.getShopId())
                .eqIfPresent(AfterSaleDO::getMerchantId, userShopDetails.getMerId())
        );
    }

    @Override
    public List<AfterSaleDO> getAfterSaleByMerAndShop() {
        UserShopDetailsVO userShopDetails = userService.getUserShopDetails();

        return tradeAfterSaleMapper.selectList(new LambdaQueryWrapperX<AfterSaleDO>()
                .eqIfPresent(AfterSaleDO::getShopId, userShopDetails.getShopId())
                .eq(AfterSaleDO::getMerchantId, userShopDetails.getMerId()));
    }

    @Override
    public Map<Integer, Long> getTabsCount(AfterSalePageReqVO pageVO) {
        UserShopDetailsVO userShopDetails = userService.getUserShopDetails();
        pageVO.setShopId(userShopDetails.getShopId());
        pageVO.setMerchantId(userShopDetails.getMerId());

        Map<Integer, Long> counts = Maps.newLinkedHashMapWithExpectedSize(8);
        // 查询申请售后的售后订单
        counts.put(AfterSaleStatusEnum.APPLY.getStatus(), tradeAfterSaleMapper.selectCount(AfterSaleStatusEnum.APPLY.getStatus(), pageVO));
        // 查询商品待退货的售后订单
        counts.put(AfterSaleStatusEnum.SELLER_AGREE.getStatus(), tradeAfterSaleMapper.selectCount(AfterSaleStatusEnum.SELLER_AGREE.getStatus(), pageVO));
        // 查询商家待收货的售后订单
        counts.put(AfterSaleStatusEnum.BUYER_DELIVERY.getStatus(), tradeAfterSaleMapper.selectCount(AfterSaleStatusEnum.BUYER_DELIVERY.getStatus(), pageVO));
        // 查询等待退款的售后订单
        counts.put(AfterSaleStatusEnum.WAIT_REFUND.getStatus(), tradeAfterSaleMapper.selectCount(AfterSaleStatusEnum.WAIT_REFUND.getStatus(), pageVO));
        // 查询退款成功的售后订单
        counts.put(AfterSaleStatusEnum.COMPLETE.getStatus(), tradeAfterSaleMapper.selectCount(AfterSaleStatusEnum.COMPLETE.getStatus(), pageVO));
        // 查询买家取消的售后订单
        counts.put(AfterSaleStatusEnum.BUYER_CANCEL.getStatus(), tradeAfterSaleMapper.selectCount(AfterSaleStatusEnum.BUYER_CANCEL.getStatus(), pageVO));
        // 查询商家拒绝的售后订单
        counts.put(AfterSaleStatusEnum.SELLER_DISAGREE.getStatus(), tradeAfterSaleMapper.selectCount(AfterSaleStatusEnum.SELLER_DISAGREE.getStatus(), pageVO));
        // 查询商家拒收货的售后订单
        counts.put(AfterSaleStatusEnum.SELLER_REFUSE.getStatus(), tradeAfterSaleMapper.selectCount(AfterSaleStatusEnum.SELLER_REFUSE.getStatus(), pageVO));
        return counts;
    }

    @Override
    public Long selectCountByStatus(Long shopId, Long merId) {
        return tradeAfterSaleMapper.selectCount(shopId, merId, AfterSaleStatusEnum.APPLY.getStatus(),
                AfterSaleStatusEnum.BUYER_DELIVERY.getStatus(),
                AfterSaleStatusEnum.WAIT_REFUND.getStatus());
    }


}
