package cn.iocoder.yudao.module.member.service.order;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.member.controller.admin.business.vo.StatisticsVo;
import cn.iocoder.yudao.module.member.controller.admin.order.vo.OrderDetailsReqVO;
import cn.iocoder.yudao.module.member.controller.admin.order.vo.OrderDetailsRespVO;
import cn.iocoder.yudao.module.member.controller.admin.order.vo.OrderMoneyRespVO;
import cn.iocoder.yudao.module.member.controller.admin.screen.vo.CarTeenInfoVO;
import cn.iocoder.yudao.module.member.controller.app.order.vo.AppOrderPageReqVO;
import cn.iocoder.yudao.module.member.controller.app.order.vo.AppOrderRespVO;
import cn.iocoder.yudao.module.member.controller.app.order.vo.AppOrderSaveReqVO;
import cn.iocoder.yudao.module.member.controller.app.order.vo.AppPageVo;
import cn.iocoder.yudao.module.member.controller.app.orderdetail.vo.AppOrderDetailRespVO;
import cn.iocoder.yudao.module.member.dal.dataobject.card.CardDO;
import cn.iocoder.yudao.module.member.dal.dataobject.diningplates.DiningPlatesDO;
import cn.iocoder.yudao.module.member.dal.dataobject.order.DishOrderDO;
import cn.iocoder.yudao.module.member.dal.dataobject.orderdetail.OrderDetailDO;
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
import cn.iocoder.yudao.module.member.dal.mysql.card.CardMapper;
import cn.iocoder.yudao.module.member.dal.mysql.group.MemberGroupMapper;
import cn.iocoder.yudao.module.member.dal.mysql.order.DishOrderMapper;
import cn.iocoder.yudao.module.member.dal.mysql.user.MemberUserMapper;
import cn.iocoder.yudao.module.member.enums.CostTypeEnum;
import cn.iocoder.yudao.module.member.enums.TimePeriodEnum;
import cn.iocoder.yudao.module.member.service.amount.DeductionService;
import cn.iocoder.yudao.module.member.service.business.BusinessService;
import cn.iocoder.yudao.module.member.service.diningplates.DiningPlatesService;
import cn.iocoder.yudao.module.member.service.money.MoneyService;
import cn.iocoder.yudao.module.member.service.orderdetail.OrderDetailService;
import cn.iocoder.yudao.module.member.service.refund.RefundService;
import cn.iocoder.yudao.module.member.util.MemberConstants;
import cn.iocoder.yudao.module.system.api.carteen.CarteenApi;
import cn.iocoder.yudao.module.system.api.carteen.dto.CarteenRespDto;
import cn.iocoder.yudao.module.system.api.deviceInfo.DeviceInfoApi;
import cn.iocoder.yudao.module.system.api.deviceInfo.dto.DeviceInfoDto;
import cn.iocoder.yudao.module.system.api.dish.DishesApi;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.*;

/**
 * 会员订单 Service 实现类
 *
 * @author 开发账号
 */
@Service
@Validated
public class OrderServiceImpl implements OrderService {

    @Resource
    private DishOrderMapper dishOrderMapper;

    @Resource
    private OrderDetailService orderDetailService;
    @Resource
    private MemberUserMapper memberUserMapper;
    @Resource
    private DeviceInfoApi deviceInfoApi;
    @Resource
    private CarteenApi carteenApi;
    @Resource
    private DishesApi dishesApi;
    @Resource
    private CardMapper cardMapper;
    @Resource
    private MemberGroupMapper groupMapper;
    @Resource
    private RefundService refundService;
    @Resource
    private BusinessService businessService;
    @Resource
    private DeductionService deductionService;
    @Resource
    private DiningPlatesService diningPlatesService;
    @Resource
    private MoneyService moneyService;

    @Override
    public Long createOrder(AppOrderSaveReqVO createReqVO) {
        // 插入
        DishOrderDO order = BeanUtils.toBean(createReqVO, DishOrderDO.class);
        dishOrderMapper.insert(order);
        // 返回
        return order.getId();
    }

    @Override
    public void updateOrder(AppOrderSaveReqVO updateReqVO) {
        // 校验存在
        DishOrderDO dishOrderDO = dishOrderMapper.selectById(updateReqVO.getId());
        if (dishOrderDO == null) {
            throw exception(ORDER_NOT_EXISTS);
        }
        //更新总价
        BigDecimal totalMoney = dishOrderDO.getTotalMoney().add(updateReqVO.getTotalMoney()).setScale(2, BigDecimal.ROUND_HALF_UP);
        updateReqVO.setTotalMoney(totalMoney);

        // 更新
        DishOrderDO updateObj = BeanUtils.toBean(updateReqVO, DishOrderDO.class);
        dishOrderMapper.updateById(updateObj);
    }

    @Override
    public void deleteOrder(Long id) {
        // 校验存在
        validateOrderExists(id);
        // 删除
        dishOrderMapper.deleteById(id);
    }

    private void validateOrderExists(Long id) {
        DishOrderDO dishOrderDO = dishOrderMapper.selectById(id);
        if (dishOrderDO == null) {
            throw exception(ORDER_NOT_EXISTS);
        }
        if ("0".equals(dishOrderDO.getOrderStatus())) {
            throw exception(ORDER_NOT_COMPLETE);
        }
    }

    @Override
    public AppOrderRespVO getOrder(Long id) {
        DishOrderDO order = dishOrderMapper.selectById(id);
        AppOrderRespVO appOrderRespVO = BeanUtils.toBean(order, AppOrderRespVO.class);
        List<AppOrderDetailRespVO> appOrderDetailRespVOS = orderDetailService.selectListByOrderId(id);
        appOrderRespVO.setDetailList(appOrderDetailRespVOS);
        BigDecimal reduce1 = appOrderDetailRespVOS.stream().filter(heat -> ObjUtil.isNotEmpty(heat.getHeat())).map(m -> BigDecimal.valueOf(m.getHeat())).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal reduce = reduce1.setScale(2, RoundingMode.HALF_UP);
        appOrderRespVO.setIntake(reduce);
        //判断时间
        int hour = order.getCreateTime().getHour();
        if (TimePeriodEnum.MORNING.getStartInt() <= hour && hour <= TimePeriodEnum.MORNING.getEndInt()) {
            appOrderRespVO.setProposeIntake(MemberConstants.PROPOSE_MORNING);
        } else if (TimePeriodEnum.MIDDAY.getStartInt() <= hour && hour <= TimePeriodEnum.MIDDAY.getEndInt()) {
            appOrderRespVO.setProposeIntake(MemberConstants.PROPOSE_NOON);
        } else {
            appOrderRespVO.setProposeIntake(MemberConstants.PROPOSE_NIGHT);
        }
        appOrderRespVO.setDifference(NumberUtil.sub(reduce, appOrderRespVO.getProposeIntake()));
        return appOrderRespVO;
    }

    @Override
    public PageResult<DishOrderDO> getOrderPage(AppOrderPageReqVO pageReqVO) {
        return dishOrderMapper.selectPage(pageReqVO);
    }

    @Override
    public PageResult<AppOrderRespVO> getOrderList(AppPageVo vo) {
        ArrayList<Long> ids = new ArrayList<>();
        if (StrUtil.isNotEmpty(vo.getMobile())) {
            List<MemberUserDO> memberUserDOS = memberUserMapper.selectList(Wrappers.<MemberUserDO>lambdaQuery().like(MemberUserDO::getMobile, vo.getMobile()));
            if (CollectionUtil.isNotEmpty(memberUserDOS)) {
                List<Long> collect = memberUserDOS.stream().map(MemberUserDO::getId).collect(Collectors.toList());
                ids.addAll(collect);
            }
        }
        if (vo.getUserId() != null) {
            ids.add(vo.getUserId());
        }

        PageResult<DishOrderDO> dishOrderDOPageResult = dishOrderMapper.selectPage(vo, Wrappers.<DishOrderDO>lambdaQuery()
                .in(CollectionUtil.isNotEmpty(ids), DishOrderDO::getUserId, ids)
                .eq(vo.getStoreId()!=null,DishOrderDO::getStoreId,vo.getStoreId())
                .eq(StrUtil.isNotBlank(vo.getOrderStatus()),DishOrderDO::getOrderStatus,vo.getOrderStatus())
                .eq(ObjUtil.isNotEmpty(vo.getBillingExist()),DishOrderDO::getBillingExist,vo.getBillingExist())
                .orderByDesc(DishOrderDO::getCreateTime));
        PageResult<AppOrderRespVO> appOrderRespVOPageResult = BeanUtils.toBean(dishOrderDOPageResult, AppOrderRespVO.class);
        List<AppOrderRespVO> list = appOrderRespVOPageResult.getList();

        List<Long> collect = list.stream().map(AppOrderRespVO::getUserId).collect(Collectors.toList());
        Map<Long, MemberUserDO> userMap = new HashMap<>();
        if(CollectionUtil.isNotEmpty(collect)){
            List<MemberUserDO> memberUserDOS = memberUserMapper.selectList(Wrappers.<MemberUserDO>lambdaQuery().in(MemberUserDO::getId, collect));
            userMap = memberUserDOS.stream().collect(Collectors.toMap(MemberUserDO::getId, userDO -> userDO));
        }

        List<CarteenRespDto> carteenList = carteenApi.getCarteenList();
        Map<Long, String> stroreMap = carteenList.stream().collect(Collectors.toMap(CarteenRespDto::getId, CarteenRespDto::getStoresName));
        for (AppOrderRespVO dishOrderDO : list) {
            List<AppOrderDetailRespVO> appOrderDetailRespVOS = orderDetailService.selectListByOrderId(dishOrderDO.getId());
//
//            for (AppOrderDetailRespVO respVo : appOrderDetailRespVOS) {
//                respVo.setDishesSumPrice(respVo.getUnitPrice());
//            }
            dishOrderDO.setStoreName(stroreMap.get(dishOrderDO.getStoreId()));
            dishOrderDO.setRefundStatus(refundService.getRefundStatus(dishOrderDO.getId()));
            dishOrderDO.setDetailList(appOrderDetailRespVOS);
            MemberUserDO memberUserDO = userMap.get(dishOrderDO.getUserId());
            if(memberUserDO!=null){
                dishOrderDO.setMobile(memberUserDO.getMobile());
                dishOrderDO.setNickname(memberUserDO.getNickname());
            }

        }
        return appOrderRespVOPageResult;
    }

    @Override
    public PageResult<OrderDetailsRespVO> getPageOrderDetails(OrderDetailsReqVO reqVO) {
        List<Long> userIds = new ArrayList<>();
        ArrayList<MemberUserDO> userList = new ArrayList<>();
        if (ObjUtil.isNotEmpty(reqVO.getUserName())
                || ObjUtil.isNotEmpty(reqVO.getUserAccount())
                || ObjUtil.isNotEmpty(reqVO.getUserJob())
                || ObjUtil.isNotEmpty(reqVO.getUserId())
                || ObjUtil.isNotEmpty(reqVO.getGroupId())
        ) {
            //根据用户属性获取ids
            List<MemberUserDO> list = memberUserMapper.selectList(new LambdaQueryWrapperX<MemberUserDO>()
                    .likeIfPresent(MemberUserDO::getNickname, reqVO.getUserName())
                    .likeIfPresent(MemberUserDO::getMobile, reqVO.getUserAccount())
                    .eqIfPresent(MemberUserDO::getCardId, reqVO.getUserJob())
                    .eqIfPresent(MemberUserDO::getId, reqVO.getUserId())
                    .inIfPresent(MemberUserDO::getId, groupMapper.getMemberList(reqVO.getGroupId())));
            userIds = list.stream().map(MemberUserDO::getId).collect(Collectors.toList());
            userList.addAll(list);
        } else {
            List<MemberUserDO> list = memberUserMapper.selectList();
            userList.addAll(list);
        }
        Map<String, LocalDateTime> timePeriod = this.getTimePeriod(reqVO.getTimePeriod());
        LocalDateTime startTime = null;
        LocalDateTime endTime = null;
        if (ObjUtil.isNotEmpty(timePeriod)) {
            startTime = timePeriod.get("start");
            endTime = timePeriod.get("end");
        }
        HashMap<Long, MemberUserDO> userMap = new HashMap<>();
        if (CollectionUtil.isNotEmpty(userList)) {
            Map<Long, MemberUserDO> collect = userList.stream().collect(Collectors.toMap(MemberUserDO::getId, s -> s));
            userMap.putAll(collect);
        }

        Map<Long, String> groupName = groupMapper.selectAllUserGroupName();

        List<CarteenRespDto> carteenList = carteenApi.getCarteenList();
        Map<Long, String> stroreMap = carteenList.stream().collect(Collectors.toMap(CarteenRespDto::getId, CarteenRespDto::getStoresName));
        //进行分页查询
        PageResult<DishOrderDO> pageResult = dishOrderMapper.selectPageList(reqVO, userIds, startTime, endTime);
        List<OrderDetailsRespVO> list = new ArrayList<>();
        for (DishOrderDO dishOrderDO : pageResult.getList()) {
            OrderDetailsRespVO bean = BeanUtils.toBean(dishOrderDO, OrderDetailsRespVO.class);
            bean.setStoreName(stroreMap.get(bean.getStoreId()));
            userDetails(bean, userMap, groupName);
            list.add(bean);
        }
        return new PageResult<>(list, pageResult.getTotal());
    }

    @Override
    public OrderDetailsRespVO getOrderDetailsAndUser(Long orderId) {
        OrderDetailsRespVO bean = BeanUtils.toBean(dishOrderMapper.selectById(orderId), OrderDetailsRespVO.class);
        userDetails(bean);
        return bean;
    }

    private void userDetails(OrderDetailsRespVO bean) {
        if(bean.getUserId()!=null){
            MemberUserDO userDO = memberUserMapper.selectById(bean.getUserId());
            bean.setGroupName(groupMapper.getGroupName(bean.getUserId()));
            bean.setUserName(userDO.getNickname());
            bean.setUserJob(userDO.getMobile());
            bean.setAvatar(userDO.getAvatar());
            bean.setPayMethods("钱包");
            bean.setUserAccount(userDO.getMobile());
            bean.setTimePeriod(TimePeriodEnum.getTimeName(bean.getCreateTime()));
            BigDecimal moneyByUsr = cardMapper.getMoneyByUsr(bean.getUserId());
            bean.setMoney(moneyByUsr);
        }
    }

    private void userDetails(OrderDetailsRespVO bean, HashMap<Long, MemberUserDO> userMap, Map<Long, String> groupName) {
        MemberUserDO userDO = userMap.get(bean.getUserId());
        bean.setTimePeriod(TimePeriodEnum.getTimeName(bean.getCreateTime()));
        if (ObjectUtil.isNotEmpty(userDO)) {
            bean.setGroupName(groupName.get(bean.getUserId()));
            bean.setUserName(userDO.getNickname());
            bean.setUserJob(userDO.getMobile());
            bean.setAvatar(userDO.getAvatar());
            bean.setPayMethods("钱包");
            bean.setUserAccount(userDO.getMobile());
        }

    }

    /**
     * @return
     * @Description: 数据类型对标 {@link CostTypeEnum}
     * @Author: qjq
     * @Date: 2024/4/1 11:18
     */
    public Map<String, LocalDateTime> getTimePeriod(String type) {
        if (TimePeriodEnum.MORNING.getCode().equalsIgnoreCase(type)) {
            return TimePeriodEnum.MORNING.getStartToEnd();
        } else if (TimePeriodEnum.MIDDAY.getCode().equalsIgnoreCase(type)) {
            return TimePeriodEnum.MIDDAY.getStartToEnd();
        } else if (TimePeriodEnum.NIGHT.getCode().equalsIgnoreCase(type)) {
            return TimePeriodEnum.NIGHT.getStartToEnd();
        } else {
            return Collections.emptyMap();
        }
    }

    @Override
    public List<DishOrderDO> getToPay(List<Long> users) {
        List<DishOrderDO> dishOrderDOS = dishOrderMapper.selectList(Wrappers.<DishOrderDO>lambdaQuery()
                .in(DishOrderDO::getUserId, users)
                .eq(DishOrderDO::getOrderStatus, DishOrderDO.INCOMPLETE));
        return dishOrderDOS;
    }

    @Override
    public List<DishOrderDO> getToPayByOrder(List<Long> orderIds) {
        List<DishOrderDO> dishOrderDOS = dishOrderMapper.selectList(Wrappers.<DishOrderDO>lambdaQuery()
                .in(DishOrderDO::getId, orderIds)
                .eq(DishOrderDO::getOrderStatus, DishOrderDO.INCOMPLETE));
        return dishOrderDOS;
    }

    @Override
    public List<DishOrderDO> getToPayByOrderAbnormal(List<Long> orderIds) {
        List<DishOrderDO> dishOrderDOS = dishOrderMapper.selectList(Wrappers.<DishOrderDO>lambdaQuery()
                .in(DishOrderDO::getId, orderIds)
                .eq(DishOrderDO::getOrderStatus, DishOrderDO.ABNORMAL));
        return dishOrderDOS;
    }

    @Override
    public void updateBatch(List<DishOrderDO> orderDOS) {
        dishOrderMapper.updateBatch(orderDOS);
    }

    @Override
    public List<DishOrderDO> getDishOrderByTime(LocalDateTime startTime, LocalDateTime endTime) {
        List<DishOrderDO> dishOrderDOS = dishOrderMapper.selectList(Wrappers.<DishOrderDO>lambdaQuery()
                .eq(DishOrderDO::getUserId, SecurityFrameworkUtils.getLoginUserId())
                .between(DishOrderDO::getCreateTime, startTime, endTime));
        return dishOrderDOS;
    }

    @Override
    public Integer selectUser(Long storeId, String time) {
        return dishOrderMapper.selectUser(storeId, time);
    }

    @Override
    public BigDecimal getSaleMoney(Long storeId, String time) {
        return dishOrderMapper.getSaleMoney(storeId, time);
    }

    @Override
    public List<CarTeenInfoVO> getCarTeenInfo() {
        List<CarTeenInfoVO> result = new ArrayList<>();
        List<CarteenRespDto> carteenList = carteenApi.getCarteenList();
        List<DeviceInfoDto> device = deviceInfoApi.getDevice();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(MemberConstants.DATE_FORMAT);
        String today = LocalDateTime.now().format(formatter);
        List<DishOrderDO> dishOrderDOS = dishOrderMapper.selectList();
        for (CarteenRespDto dto : carteenList) {
            CarTeenInfoVO carTeenInfoVO = new CarTeenInfoVO();
            long deviceNum = device.stream().filter(vo -> vo.getCarteenId().equals(dto.getId())).count();
            carTeenInfoVO.setDeviceNum(String.valueOf(deviceNum));

            List<DishOrderDO> carteenOrderList = dishOrderDOS.stream().filter(dishOrderDO -> dishOrderDO.getStoreId().equals(dto.getId())).collect(Collectors.toList());
            BigDecimal totalMoney = carteenOrderList.stream().map(DishOrderDO::getTotalMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
            carTeenInfoVO.setTodayMoney(totalMoney);

            List<DishOrderDO> todayCarteenOrderList = carteenOrderList.stream().filter(vo -> today.equals(vo.getCreateTime().format(formatter))).collect(Collectors.toList());
            BigDecimal todayMoney = todayCarteenOrderList.stream().map(DishOrderDO::getTotalMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
            carTeenInfoVO.setTodayMoney(todayMoney);
            long peopleNUm = todayCarteenOrderList.stream().map(DishOrderDO::getUserId).distinct().count();
            carTeenInfoVO.setPeopleNUm(String.valueOf(peopleNUm));

            carTeenInfoVO.setStoresName(dto.getStoresName());
            carTeenInfoVO.setStoreId(dto.getId());

            result.add(carTeenInfoVO);
        }
        return result;
    }

    /**
     * @Description: 根据会员编号，获得会员余额,充值金额,消费金额
     * @Author: qjq
     * @Date: 2024/4/24 上午9:52
     */
    @Override
    public OrderMoneyRespVO getUserMeney(Long userId, Long carteenId) {
        OrderMoneyRespVO orderMoneyRespVO = new OrderMoneyRespVO();
        //获取充值的金额
        BigDecimal add = cardMapper.selectAddMoney(userId, CardDO.ADD);
        if (add == null) {
            add = BigDecimal.ZERO;
        }
        orderMoneyRespVO.setRechargeMoney(add);
        //消费的金额
        BigDecimal minus = cardMapper.selectReduceMoney(userId, CardDO.MINUS);
        if (minus == null) {
            minus = BigDecimal.ZERO;
        }
        orderMoneyRespVO.setConsumeMoney(minus);
        //获取会员余额
        MemberUserDO memberUserDO = memberUserMapper.selectById(userId);
        orderMoneyRespVO.setCurrentMoney(memberUserDO.getWxAmount());
        orderMoneyRespVO.setUserId(userId);
        orderMoneyRespVO.setCashMoney(memberUserDO.getCashAmount());
        orderMoneyRespVO.setDebtMoney(BigDecimal.ZERO);
        if(memberUserDO.getMoney().compareTo(BigDecimal.ZERO)<0){
            orderMoneyRespVO.setDebtMoney(memberUserDO.getMoney());
        }
        BigDecimal wxRechargeMoney = cardMapper.selectWxMoney(userId);
        orderMoneyRespVO.setWxRechargeMoney(wxRechargeMoney);
        return orderMoneyRespVO;
    }

    @Override
    public Map<String, Object> getMoneyAndPeople(Long storeId) {
        BigDecimal total = BigDecimal.ZERO;
        int size = 0;
        List<DishOrderDO> dishOrderDOS = dishOrderMapper.selectList(Wrappers.<DishOrderDO>lambdaQuery()
                .eq(DishOrderDO::getStoreId, storeId)
                .apply("DATE(create_time) = DATE(NOW())"));
        if (CollectionUtil.isNotEmpty(dishOrderDOS)) {
            BigDecimal reduce = dishOrderDOS.stream().map(DishOrderDO::getTotalMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
            total = reduce;
            size = dishOrderDOS.stream().map(DishOrderDO::getUserId).distinct().collect(Collectors.toList()).size();
        }
        Map<String, Object> map = new HashMap<>();
        map.put("total", total);
        map.put("size", size);
        return map;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void reduction(Long orderId, BigDecimal money) {
        DishOrderDO dishOrderDO = dishOrderMapper.selectById(orderId);
        if(dishOrderDO.getTotalMoney().compareTo(money) < 0){
            throw exception(ORDER_MONEY_NOT_ENOUGH);
        }

        dishOrderDO.setReductionState("1");
        if (dishOrderDO.getOrderStatus().equals("1")) {
            dishOrderDO.setReductionAmount(dishOrderDO.getReductionAmount().add(money));
            //更改订单
            BigDecimal wxAmount = BigDecimal.ZERO;
            BigDecimal cashAmount = BigDecimal.ZERO;
            BigDecimal giftAmount = BigDecimal.ZERO;

            dishOrderDO.setTotalMoney(dishOrderDO.getTotalMoney().subtract(money));
            dishOrderDO.setRefundAmount(dishOrderDO.getRefundAmount().subtract(money));
            if (dishOrderDO.getWxAmount().compareTo(money) >= 0) {
                dishOrderDO.setWxAmount(dishOrderDO.getWxAmount().subtract(money));
                wxAmount = wxAmount.add(money);
            } else {
                BigDecimal leftMoney = money.subtract(dishOrderDO.getWxAmount());
                wxAmount = wxAmount.add(dishOrderDO.getWxAmount());
                dishOrderDO.setWxAmount(BigDecimal.ZERO);
                if (dishOrderDO.getCashAmount().compareTo(leftMoney) > 0) {
                    dishOrderDO.setCashAmount(dishOrderDO.getCashAmount().subtract(leftMoney));
                    cashAmount = cashAmount.add(leftMoney);
                } else {
                    BigDecimal leftMoney1 = leftMoney.subtract(dishOrderDO.getCashAmount());
                    cashAmount = cashAmount.add(dishOrderDO.getCashAmount());
                    dishOrderDO.setCashAmount(BigDecimal.ZERO);

                    dishOrderDO.setGiftAmount(dishOrderDO.getGiftAmount().subtract(leftMoney1));
                    giftAmount = giftAmount.add(leftMoney1);
                }
            }

            //退款
            deductionService.reduction(dishOrderDO.getUserId(), money, giftAmount, cashAmount, wxAmount, dishOrderDO.getStoreId());

            //更新营业数据
            if (dishOrderDO.getOrderStatus().equals(DishOrderDO.COMPLETE)) {
                StatisticsVo statisticsVo = new StatisticsVo();
                statisticsVo.setCarteenId(dishOrderDO.getStoreId());
                statisticsVo.setTotalMoney(money.negate());
                statisticsVo.setOrderSum(0);
                statisticsVo.setReduceMoney(money);
                statisticsVo.setTime(dishOrderDO.getCreateTime());
                businessService.updateStatistics(statisticsVo);
            }

        } else if(dishOrderDO.getOrderStatus().equals("0")){
            BigDecimal orderMoney = diningPlatesService.getOrderMoney(orderId);
            BigDecimal add = dishOrderDO.getReductionAmount().add(money);
            if (orderMoney != null && orderMoney.compareTo(add) < 0) {
                add = orderMoney;
            }
            dishOrderDO.setReductionAmount(add);
        }else {
            throw exception(ORDER_STATUS_NOT_ALLOW);
        }
        dishOrderMapper.updateById(dishOrderDO);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void customize(String mobile, BigDecimal money, Long carteenId, String type, String date) {
        //订单处理
        MemberUserDO memberUserDO = memberUserMapper.selectOne(Wrappers.<MemberUserDO>lambdaQuery().eq(MemberUserDO::getMobile, mobile));
        if (memberUserDO == null) {
            throw exception(USER_NOT_EXISTS);
        }
        String dateTime = date;
        if(CostTypeEnum.MORNING.getCode().equals(type)){
            dateTime = dateTime+" 08:00:00";
        }else if (CostTypeEnum.NOON.getCode().equals(type)){
            dateTime = dateTime+" 12:00:00";
        }else if (CostTypeEnum.NIGHT.getCode().equals(type)){
            dateTime = dateTime+" 17:00:00";
        }
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime now = LocalDateTime.parse(dateTime, formatter);


        DishOrderDO dishOrderDO = new DishOrderDO();
        dishOrderDO.setStoreId(carteenId);
        dishOrderDO.setOrderStatus(DishOrderDO.COMPLETE);
        dishOrderDO.setTotalMoney(money);
        dishOrderDO.setUserId(memberUserDO.getId());
        dishOrderDO.setPayMethods(type);
        dishOrderDO.setDiningPlatesNum("000001");
        dishOrderDO.setCashAmount(money);
        dishOrderDO.setRefundAmount(money);
        dishOrderDO.setCreateTime(now);

        dishOrderMapper.insert(dishOrderDO);
        //订单详情处理
        OrderDetailDO orderDetailDO = new OrderDetailDO();
        orderDetailDO.setOrderId(dishOrderDO.getId());
        orderDetailDO.setDishesName("自定义");
        orderDetailDO.setPrice(money);
        orderDetailDO.setDishesId(-1L);
        orderDetailService.insertOne(orderDetailDO);
        //扣费处理
        deductionService.deduct(memberUserDO.getId(), money, type,carteenId,date);
        //更新营业数据
        StatisticsVo statisticsVo = new StatisticsVo();
        statisticsVo.setCarteenId(dishOrderDO.getStoreId());
        statisticsVo.setTotalMoney(dishOrderDO.getTotalMoney());
        statisticsVo.setOrderSum(1);
        statisticsVo.setReduceMoney(dishOrderDO.getReductionAmount());
        statisticsVo.setTime(dishOrderDO.getCreateTime());
        statisticsVo.setOrderId(dishOrderDO.getId());
        businessService.updateStatistics(statisticsVo);

    }

    @Override
    public void abnormalHandle(Long orderId, String mobile) {
        DishOrderDO dishOrderDO = dishOrderMapper.selectById(orderId);
        if(dishOrderDO == null){
            throw exception(ORDER_NOT_EXISTS);
        }
        List<MemberUserDO> memberUserDOS = memberUserMapper.selectList(new LambdaQueryWrapperX<MemberUserDO>()
                .eq(MemberUserDO::getMobile, mobile));
        if(CollectionUtil.isEmpty(memberUserDOS)){
            throw exception(USER_NOT_EXISTS);
        }
        dishOrderDO.setUserId(memberUserDOS.get(0).getId());
        DiningPlatesDO diningPlatesDO = diningPlatesService.getDiningPlatesByNum(dishOrderDO.getDiningPlatesNum(), dishOrderDO.getStoreId());

        if(dishOrderDO.getTotalMoney().compareTo(BigDecimal.ZERO)>0){
            //扣费处理
            deductionService.abnormalOrderDeduct(dishOrderDO);
            diningPlatesService.updateBind(Collections.singletonList(diningPlatesDO.getId()));
        }else {
            diningPlatesDO.setUserId(dishOrderDO.getUserId());
            diningPlatesService.updateById(diningPlatesDO);
            dishOrderDO.setOrderStatus(DishOrderDO.INCOMPLETE);
        }
        dishOrderMapper.updateById(dishOrderDO);
    }

    @Override
    public void orderTransfer(Long orderId, String mobile) {
        List<MemberUserDO> memberUserDOS = memberUserMapper.selectList(new LambdaQueryWrapperX<MemberUserDO>()
                .eq(MemberUserDO::getMobile, mobile));
        if(CollectionUtil.isEmpty(memberUserDOS)){
            throw exception(USER_NOT_EXISTS);
        }
        DishOrderDO dishOrderDO = dishOrderMapper.selectById(orderId);
        if(dishOrderDO == null){
            throw exception(ORDER_NOT_EXISTS);
        }
        MemberUserDO memberUserDO = memberUserDOS.get(0);
        //扣费处理
        deductionService.orderTransferHandle(dishOrderDO,memberUserDO.getId());
        dishOrderDO.setTransferState("1");
        dishOrderDO.setTransferTime(LocalDateTime.now());
        dishOrderMapper.updateById(dishOrderDO);
    }
}