package com.yiqi.order.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.yiqi.common.exception.ServiceException;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yiqi.activity.domain.ActivityCouponInfo;
import com.yiqi.activity.domain.ActivityCouponItem;
import com.yiqi.activity.domain.ActivityInfo;
import com.yiqi.activity.service.IActivityCouponInfoService;
import com.yiqi.activity.service.IActivityCouponItemService;
import com.yiqi.activity.service.IActivityInfoService;
import com.yiqi.app.domain.AppCouponItem;
import com.yiqi.app.domain.AppCouponType;
import com.yiqi.app.service.IAppCouponItemService;
import com.yiqi.app.service.IAppCouponTypeService;
import com.yiqi.app.service.IAppUserBillMstrService;
import com.yiqi.common.core.domain.R;
import com.yiqi.common.enums.*;
import com.yiqi.common.exception.GlobalException;
import com.yiqi.common.utils.DateUtils;
import com.yiqi.common.utils.OrderNoUtils;
import com.yiqi.common.utils.SecurityUtils;
import com.yiqi.delay.DelayQueueCache;
import com.yiqi.order.domain.OrderActivity;
import com.yiqi.order.domain.OrderActivityItem;
import com.yiqi.order.domain.dto.*;
import com.yiqi.order.domain.vo.OrderActivityPayResultVO;
import com.yiqi.order.domain.vo.OrderActivityVO;
import com.yiqi.order.mapper.OrderActivityMapper;
import com.yiqi.order.service.IOrderActivityItemService;
import com.yiqi.order.service.IOrderActivityService;
import com.yiqi.order.service.IPayService;
import com.yiqi.recharge.domain.dto.ConsumeOrderDTO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 活动订单Service业务层处理
 *
 * @author ruoyi
 * @date 2023-09-30
 */
@Service
public class OrderActivityServiceImpl extends ServiceImpl<OrderActivityMapper, OrderActivity> implements IOrderActivityService {

    @Autowired
    private IAppCouponTypeService appCouponTypeService;
    @Autowired
    private IAppCouponItemService appCouponItemService;
    @Autowired
    private IActivityInfoService activityInfoService;
    @Autowired
    private IActivityCouponInfoService activityCouponInfoService;
    @Autowired
    private OrderNoUtils orderNoUtils;
    @Autowired
    private IActivityCouponItemService activityCouponItemService;
    @Autowired
    private IOrderActivityItemService orderActivityItemService;
    @Autowired
    private IPayService payService;
    @Autowired
    private IAppUserBillMstrService appUserBillMstrService;
    @Autowired
    private DelayQueueCache delayQueueCache;

    /**
     * 查询活动订单
     *
     * @param id 活动订单主键
     * @return 活动订单
     */
    @Override
    public OrderActivity selectOrderActivityById(Long id) {
        return baseMapper.selectOrderActivityById(id);
    }

    /**
     * 查询活动订单列表
     *
     * @param orderActivityQueryDTO 活动订单
     * @return 活动订单
     */
    @Override
    public List<OrderActivityVO> selectOrderActivityList(OrderActivityQueryDTO orderActivityQueryDTO) {
        return baseMapper.selectOrderActivityList(orderActivityQueryDTO);
    }

    /**
     * 修改活动订单
     *
     * @param orderActivity 活动订单
     * @return 结果
     */
    @Override
    public int updateOrderActivity(OrderActivity orderActivity) {
        orderActivity.setUpdateTime(DateUtils.getNowDate());
        return baseMapper.updateOrderActivity(orderActivity);
    }

    /**
     * 批量删除活动订单
     *
     * @param ids 需要删除的活动订单主键
     * @return 结果
     */
    @Override
    public int deleteOrderActivityByIds(Long[] ids) {
        return baseMapper.deleteOrderActivityByIds(ids);
    }

    /**
     * 删除活动订单信息
     *
     * @param id 活动订单主键
     * @return 结果
     */
    @Override
    public int deleteOrderActivityById(Long id) {
        return baseMapper.deleteOrderActivityById(id);
    }

    /**
     * 新增活动订单
     *
     * @param activityOrderDTO 活动订单
     * @return 结果
     */
    @Override
    public OrderActivityPayResultVO insertOrderActivity(ActivityOrderDTO activityOrderDTO) {
        OrderActivity orderActivity = new OrderActivity();
        // 保存订单
        this.buildOrderActivity(orderActivity, activityOrderDTO);
        // 处理减库存
        this.handleMinusCouponStock(orderActivity);

        OrderActivityPayResultVO orderActivityPayResultVO = new OrderActivityPayResultVO();
        // 支付流程
        this.handlePay(orderActivity, orderActivityPayResultVO, activityOrderDTO);
        return orderActivityPayResultVO;
    }

    /**
     * 支付成功后，处理活动订单
     *
     * @param orderNo
     * @return
     */
    @Override
    public R handlePaySuccessUpdateActivityOrderStatus(String orderNo) {
        OrderActivity orderActivity = this.getOne(new QueryWrapper<OrderActivity>().lambda().eq(OrderActivity::getOrderNo, orderNo));
        if (orderActivity == null) {
            throw new ServiceException("活动订单不存在," + orderNo);
        }
        if (PayStatus.HAS_PAY.getCode().equals(orderActivity.getPayStatus())) {
            return R.ok();
        }
        orderActivity.setPayStatus(PayStatus.HAS_PAY.getCode());
        orderActivity.setOrderStatus(OrderActivityStatusType.CONFIRM_RECEIVE.getCode());
        orderActivity.setPayTime(DateUtils.getNowDate());
        orderActivity.buildUpdateData();
        this.updateById(orderActivity);
        // 添加订单优惠券给客户
        this.addCoupon4AppUser(orderActivity);
        // 记录账单
//        appUserBillMstrService.consumeRecord(ConsumeOrderDTO.buildOrderActivityData(orderActivity));
        return R.ok();
    }

    /**
     * 活动订单-处理支付失败,自动取消
     *
     * @param orderNo
     * @return 处理支付失败
     */
    @Override
    public String handleCancelActivityOrder(String orderNo) {
        OrderActivity orderActivity = this.getOne(new QueryWrapper<OrderActivity>().lambda()
                .eq(OrderActivity::getOrderNo, orderNo));
        if (orderActivity == null) {
            log.debug("活动订单不存在，订单编号：" + orderNo);
            return "订单不存在";
        }
        if (OrderActivityStatusType.REFUND.getCode().equals(orderActivity.getOrderStatus())) {
            log.debug("活动订单已退款，无法取消，订单编号：" + orderNo);
            return "活动订单已退款，无法取消";
        }
        if (!OrderActivityStatusType.NO_PAY.getCode().equals(orderActivity.getOrderStatus())) {
            throw new GlobalException("订单状态已支付，无法取消");
        }
        //返回优惠券库存
        this.handleAddCouponStock(orderActivity);
        // 更新订单状态
        orderActivity.setOrderStatus(OrderActivityStatusType.CANCEL_ORDER.getCode());
        orderActivity.setRemark("支付失败取消订单");
        orderActivity.setPayTime(null);
        orderActivity.buildUpdateData();
        baseMapper.updateById(orderActivity);
        return "取消订单成功";
    }

    /**
     * 活动订单-总部撤单申请
     */
    @Override
    public int refundOrderActivityApply(OrderActivityRefundDTO orderActivityRefundDTO, String sourceType) {
        OrderActivity orderActivity = baseMapper.selectById(orderActivityRefundDTO.getOrderId());
        if (orderActivity == null) {
            throw new GlobalException("活动订单不存在");
        }
        if (SourceType.MANAGER.getCode().equals(sourceType)) {
            // 操作人校验
            if (!SecurityUtils.getLoginUser().getSourceType().equals(SourceType.MANAGER.getCode())) {
                throw new ServiceException("当前登录人没有权限操作");
            }
        }
        if (OrderActivityStatusType.REFUND.getCode().equals(orderActivity.getOrderStatus())) {
            throw new GlobalException("活动订单已退款，无法继续申请退款操作");
        }
        if (OrderGoodsStatusType.NO_PAY.getCode().equals(orderActivity.getOrderStatus())) {
            throw new GlobalException("活动订单未支付，不能操作退单");
        }
        // 超过3个月不能退单
        if ((DateUtils.getNowDate().compareTo(DateUtils.addMonths(orderActivity.getCreateTime(), 3))) > 0) {
            throw new GlobalException("活动订单已经超过退单时间，不能操作退单");
        }
        if (!OrderSourceType.APP.getCode().equals(orderActivity.getOrderSource())) {
            throw new GlobalException("非APP下单，无法操作退款申请");
        }

        // 更新订单状态
        orderActivity.setRefundContent(orderActivityRefundDTO.getRefundReason());
        orderActivity.setRefundStatus(OrderRefundStatus.REFUNDING.getCode());
        orderActivity.setRefundApplyTime(DateUtils.getNowDate());
        orderActivity.setRefundAmount(orderActivity.getPayAmount());
        orderActivity.setRefundTime(DateUtils.getNowDate());
        orderActivity.buildUpdateData();
        baseMapper.updateById(orderActivity);

        // 退款
        if (orderActivity.getPayType().equals(PayType.WECHAT.getCode()) || orderActivity.getPayType().equals(PayType.ALIPAY.getCode())) {
            PayRefundDTO payRefundDTO = new PayRefundDTO(orderActivity.getPayType(), orderActivity.getOrderNo(), orderActivity.getPayAmount(), null, orderActivity.getOutTradeOrderNo(), null);
            //执行微信退款逻辑
            payRefundDTO.setTotalAmount(orderActivity.getPayAmount());
            payRefundDTO.setStoreId(orderActivity.getOrgId());
            RefundResponseDTO refundResponse = payService.refundApply(payRefundDTO);

            if (refundResponse.getRefundResult().equals(PayResult.fail.getCode())) {
                refundError(orderActivity.getOrderNo());
            }
        }
        return 1;
    }

    @Override
    public R refundSuccess(String orderNo) {
        OrderActivity orderActivity = getOne(new QueryWrapper<OrderActivity>().lambda().eq(OrderActivity::getOrderNo, orderNo));
        if (orderActivity == null) {
            throw new ServiceException("未查询到订单");
        }
        orderActivity.setOrderStatus(OrderGoodsStatusType.REFUND.getCode());
        orderActivity.setRefundStatus(OrderRefundStatus.REFUND_SUCCESS.getCode());
        baseMapper.updateById(orderActivity);
        // 删除客户优惠卷
        this.minusCoupon4AppUser(orderActivity);
        //返回优惠券库存
        this.handleAddCouponStock(orderActivity);
        //此处添加退款记录
//        appUserBillMstrService.save(appUserBillMstrService.buildBillMstr(ConsumeOrderDTO.buildOrderActivityRefundData(orderActivity)));
        return R.ok();
    }

    @Override
    public R refundClosed(String orderNo) {
        OrderActivity orderActivity = getOne(new QueryWrapper<OrderActivity>().lambda().eq(OrderActivity::getOrderNo, orderNo));
        if (orderActivity == null) {
            throw new ServiceException("未查询到订单");
        }
        orderActivity.setRefundStatus(OrderRefundStatus.REFUND_CANCEL.getCode());
        updateById(orderActivity);
        return R.ok();
    }

    @Override
    public R refundError(String orderNo) {
        OrderActivity orderActivity = getOne(new QueryWrapper<OrderActivity>().lambda().eq(OrderActivity::getOrderNo, orderNo));
        if (orderActivity == null) {
            throw new ServiceException("未查询到订单");
        }
        orderActivity.setRefundStatus(OrderRefundStatus.ERROR.getCode());
        updateById(orderActivity);
        return R.ok();
    }

    private void checkCouponIsUse(OrderActivity orderActivity) {
        long count = appCouponItemService.count(new QueryWrapper<AppCouponItem>().lambda()
                .eq(AppCouponItem::getActivityInfoId, orderActivity.getActivityId())
                .eq(AppCouponItem::getOrderNo, orderActivity.getOrderNo())
                .eq(AppCouponItem::getIsUsed, SysBoolType.YES.getCode())
                .eq(AppCouponItem::getDelFlag, StatusType.OK.getCode()));
        if (count > 0) {
            throw new ServiceException("该活动订单的优惠券已被使用，无法操作撤单");
        }
    }

    /**
     * 添加订单优惠券给客户
     *
     * @param orderActivity
     */
    public void addCoupon4AppUser(OrderActivity orderActivity) {
        ActivityCouponInfo activityCouponInfo = activityCouponInfoService.getOne(new QueryWrapper<ActivityCouponInfo>().lambda()
                .eq(ActivityCouponInfo::getActivityId, orderActivity.getActivityId()));
        // 查询活动设置添加得优惠券
        List<ActivityCouponItem> couponItemList = activityCouponItemService.list(new QueryWrapper<ActivityCouponItem>().lambda()
                .eq(ActivityCouponItem::getActivityId, orderActivity.getActivityId())
                .ge(ActivityCouponItem::getEndDate, DateUtils.getNowDate()));
        List<Long> couponTypeIdList = couponItemList.stream().map(ActivityCouponItem::getCouponTypeId).distinct().collect(Collectors.toList());
        // 查询设置的优惠券信息
        List<AppCouponType> appCouponTypeList = appCouponTypeService.list(new QueryWrapper<AppCouponType>().lambda()
                .in(AppCouponType::getId, couponTypeIdList)
                .eq(AppCouponType::getStatus, StatusType.OK.getCode())
                .eq(AppCouponType::getDelFlag, StatusType.OK.getCode()));
        List<AppCouponItem> appCouponItemList = new ArrayList<>();
        for (AppCouponType appCouponType : appCouponTypeList) {
            AppCouponItem appCouponItem = new AppCouponItem();
            BeanUtils.copyProperties(appCouponType, appCouponItem);
            appCouponItem.setSource(CouponSourceEnum.ACTIVITY_SEND.getCode());
            appCouponItem.setAppUserId(orderActivity.getAppUserId());
            appCouponItem.setOrderNo(orderActivity.getOrderNo());
            appCouponItem.setCouponTypeId(appCouponType.getId());
            appCouponItem.setIsUnique(appCouponType.getIsUnique());
            appCouponItem.setCouponTypeTitle(appCouponType.getTitle());
            appCouponItem.setActivityInfoId(orderActivity.getActivityId());
            appCouponItem.setStoreId(orderActivity.getOrgId());
            //适用范围 1：全部衣服 2：指定衣服
            appCouponItem.setUseScope(appCouponType.getUseScope());
            //门店适用范围 1：适用领取本店 2：活动参与门店
            appCouponItem.setStoreScope(activityCouponInfo.getStoreScope());
            appCouponItem.setIsUsed(SysBoolType.NO.getCode());
            appCouponItem.setDelFlag(StatusType.OK.getCode());
            appCouponItem.buildCreateData();
            appCouponItemList.add(appCouponItem);
        }
        appCouponItemService.saveBatch(appCouponItemList);
    }

    /**
     * 删除客户的订单优惠券
     *
     * @param orderActivity
     */
    public void minusCoupon4AppUser(OrderActivity orderActivity) {
        // 校验优惠券是否使用
        this.checkCouponIsUse(orderActivity);

        appCouponItemService.update(new UpdateWrapper<AppCouponItem>().lambda()
                .eq(AppCouponItem::getActivityInfoId, orderActivity.getActivityId())
                .eq(AppCouponItem::getOrderNo, orderActivity.getOrderNo())
                .eq(AppCouponItem::getIsUsed, SysBoolType.NO.getCode())
                .set(AppCouponItem::getDelFlag, StatusType.DELETED.getCode()));

    }

    /**
     * 保存活动订单
     *
     * @param orderActivity
     * @param activityOrderDTO
     */
    private void buildOrderActivity(OrderActivity orderActivity, ActivityOrderDTO activityOrderDTO) {
        BeanUtils.copyProperties(activityOrderDTO, orderActivity);
        orderActivity.setOrderNo(orderNoUtils.getActivityOrderNo());
        orderActivity.setDelFlag(UserStatus.OK.getCode());
        // 查询活动信息
        long count = activityInfoService.count(new QueryWrapper<ActivityInfo>().lambda()
                .eq(ActivityInfo::getId, activityOrderDTO.getActivityId())
                .eq(ActivityInfo::getStatus, StatusType.OK.getCode())
                .eq(ActivityInfo::getDelFlag, StatusType.OK.getCode()));
        if (count == 0) {
            throw new ServiceException("未能查询到该活动，无法下单");
        }
        ActivityCouponInfo activityCouponInfo = activityCouponInfoService.getOne(new QueryWrapper<ActivityCouponInfo>().lambda()
                .eq(ActivityCouponInfo::getActivityId, activityOrderDTO.getActivityId()), false);
        if (activityCouponInfo == null) {
            log.debug("该活动明细为空，活动id：" + activityOrderDTO.getActivityId());
            throw new ServiceException("该活动明细为空，无法下单");
        }
        orderActivity.setPayAmount(activityCouponInfo.getPrice());
        orderActivity.setOrderStatus(OrderActivityStatusType.NO_PAY.getCode());
        orderActivity.buildCreateData();
        this.save(orderActivity);
    }

    /**
     * 处理减库存
     *
     * @param orderActivity
     */
    private void handleMinusCouponStock(OrderActivity orderActivity) {
        // 查询活动设置添加得优惠券
        List<ActivityCouponItem> couponItemList = activityCouponItemService.list(new QueryWrapper<ActivityCouponItem>().lambda()
                .eq(ActivityCouponItem::getActivityId, orderActivity.getActivityId())
                .eq(ActivityCouponItem::getDelFlag, StatusType.OK.getCode())
                .ge(ActivityCouponItem::getEndDate, DateUtils.getNowDate()));
        if (CollUtil.isEmpty(couponItemList)) {
            log.debug("该活动未设置优惠券，活动id：" + orderActivity.getActivityId());
            throw new ServiceException("该活动未设置优惠券，无法下单");
        }
        List<Long> couponTypeIdList = couponItemList.stream().map(ActivityCouponItem::getCouponTypeId).distinct().collect(Collectors.toList());
        // 查询设置的优惠券信息
        List<AppCouponType> appCouponTypeList = appCouponTypeService.list(new QueryWrapper<AppCouponType>().lambda()
                .in(AppCouponType::getId, couponTypeIdList)
                .eq(AppCouponType::getStatus, StatusType.OK.getCode())
                .eq(AppCouponType::getDelFlag, StatusType.OK.getCode()));
        if (CollUtil.isEmpty(appCouponTypeList)) {
            throw new ServiceException("无法查询到活动添加的优惠券信息，无法下单");
        }
        if (appCouponTypeList.size() != couponTypeIdList.size()) {
            throw new ServiceException("活动添加的优惠券中，部分优惠券信息不存在，无法下单");
        }
        Map<Long, AppCouponType> couponTypeMap = appCouponTypeList.stream().collect(Collectors.toMap(AppCouponType::getId, AppCouponType -> AppCouponType));
        // 校验优惠券库存 并保存明细关联表
        List<OrderActivityItem> orderActivityItemList = this.checkStockAndSaveOrderActivityItem(orderActivity, couponItemList, couponTypeMap);
        // 处理减库存
        activityCouponItemService.minusActivityCouponStockByOrder(orderActivityItemList);
    }

    /**
     * 处理加库存
     *
     * @param orderActivity
     */
    private void handleAddCouponStock(OrderActivity orderActivity) {
        // 查询活动设置添加得优惠券
        List<OrderActivityItem> orderActivityItems = orderActivityItemService.list(new QueryWrapper<OrderActivityItem>().lambda()
                .eq(OrderActivityItem::getOrderNo, orderActivity.getActivityId()));
        // 处理减库存
        activityCouponItemService.addActivityCouponStockByOrder(orderActivityItems);
    }

    /**
     * 校验优惠券库存 并保存明细关联表
     *
     * @param orderActivity
     * @param couponItemList
     * @param couponTypeMap
     */
    private List<OrderActivityItem> checkStockAndSaveOrderActivityItem(OrderActivity orderActivity, List<ActivityCouponItem> couponItemList, Map<Long, AppCouponType> couponTypeMap) {
        List<OrderActivityItem> orderActivityItemList = new ArrayList<>();
        for (ActivityCouponItem couponItem : couponItemList) {
            if (couponItem.getCouponStock() <= 0) {
                log.debug("该活动的优惠券库存不足，活动id：" + couponItem.getActivityId() + "优惠券类型id" + couponItem.getCouponTypeId());
                throw new ServiceException("该活动的优惠券库存不足，无法下单");
            }
            orderActivityItemList.add(OrderActivityItem.buildOrderActivityItem(orderActivity, couponTypeMap.get(couponItem.getCouponTypeId())));
        }
        // 保存明细关联表
        orderActivityItemService.saveBatch(orderActivityItemList);

        return orderActivityItemList;
    }

    /**
     * 支付流程
     *
     * @param orderActivity
     * @param orderActivityPayResultVO
     * @param activityOrderDTO
     */
    private void handlePay(OrderActivity orderActivity, OrderActivityPayResultVO orderActivityPayResultVO, ActivityOrderDTO activityOrderDTO) {
        orderActivityPayResultVO.setAppPayRespVO(payService.appPay(PayOrderAppDTO.buildActivityOrderPayData(orderActivity, activityOrderDTO.getPlatform())));
    }


}
