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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
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.module.member.controller.admin.business.vo.StatisticsVo;
import cn.iocoder.yudao.module.member.controller.admin.storegoodsinventory.vo.AddReqVO;
import cn.iocoder.yudao.module.member.controller.admin.storegoodsinventory.vo.GoodsInfoReqVO;
import cn.iocoder.yudao.module.member.controller.admin.storeorder.vo.*;
import cn.iocoder.yudao.module.member.controller.admin.storerefund.vo.StoreRefundSaveReqVO;
import cn.iocoder.yudao.module.member.controller.app.store.dto.*;
import cn.iocoder.yudao.module.member.controller.app.store.vo.UserInfoVo;
import cn.iocoder.yudao.module.member.controller.app.storeorder.vo.AppStoreGoodsDetail;
import cn.iocoder.yudao.module.member.controller.app.storeorder.vo.AppStoreOrderVO;
import cn.iocoder.yudao.module.member.controller.app.storeorder.vo.CardDto;
import cn.iocoder.yudao.module.member.dal.dataobject.storediscount.StoreDiscountDO;
import cn.iocoder.yudao.module.member.dal.dataobject.storeorder.StoreOrderDO;
import cn.iocoder.yudao.module.member.dal.dataobject.storeorderdetail.StoreOrderDetailDO;
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
import cn.iocoder.yudao.module.member.dal.mysql.storeorder.StoreOrderMapper;
import cn.iocoder.yudao.module.member.enums.*;
import cn.iocoder.yudao.module.member.service.amount.AmountService;
import cn.iocoder.yudao.module.member.service.amount.DeductionService;
import cn.iocoder.yudao.module.member.service.amount.LockManager;
import cn.iocoder.yudao.module.member.service.group.MemberGroupService;
import cn.iocoder.yudao.module.member.service.money.MoneyService;
import cn.iocoder.yudao.module.member.service.storebusiness.StoreBusinessService;
import cn.iocoder.yudao.module.member.service.storediscount.StoreDiscountService;
import cn.iocoder.yudao.module.member.service.storegoodsinventory.StoreGoodsInventoryService;
import cn.iocoder.yudao.module.member.service.storeorderdetail.StoreOrderDetailService;
import cn.iocoder.yudao.module.member.service.storerefund.StoreRefundService;
import cn.iocoder.yudao.module.member.service.storeshoppingcart.StoreShoppingCartService;
import cn.iocoder.yudao.module.member.service.user.MemberUserService;
import cn.iocoder.yudao.module.member.util.MemberConstants;
import cn.iocoder.yudao.module.member.util.QRCodeWithJWTUtil;
import cn.iocoder.yudao.module.system.api.cashregisterinfo.CashregisterinfoApi;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.data.redis.core.StringRedisTemplate;
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.ArrayList;
import java.util.List;
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.*;
import static cn.iocoder.yudao.module.member.service.amount.LockManager.getStoreOrderLock;

/**
 * 商品订单 Service 实现类
 *
 * @author 管理员
 */
@Service
@Validated
public class StoreOrderServiceImpl implements StoreOrderService {

    @Resource
    private StoreOrderMapper storeOrderMapper;

    @Resource
    private StoreOrderDetailService orderDetailService;

    @Resource
    private MoneyService moneyService;

    @Resource
    private StoreDiscountService storeDiscountService;

    @Resource
    private MemberUserService userService;

    @Resource
    private DeductionService deductionService;

    @Resource
    private CashregisterinfoApi cashregisterinfoApi;
    @Resource
    private StoreBusinessService storeBusinessService;
    @Resource
    private AmountService amountService;
    @Resource
    private StoreGoodsInventoryService storeGoodsInventoryService;
    @Resource
    private StoreRefundService storeRefundService;
    @Resource
    private StoreShoppingCartService storeShoppingCartService;

    @Resource
    private MemberGroupService memberGroupService;

    @Resource
    private StringRedisTemplate storeOrderRedisTemplate;

    @Override
    public Integer createStoreOrder(StoreOrderSaveReqVO createReqVO) {
        // 插入
        StoreOrderDO storeOrder = BeanUtils.toBean(createReqVO, StoreOrderDO.class);
        storeOrderMapper.insert(storeOrder);
        // 返回
        return storeOrder.getOrderId();
    }

    @Override
    public void updateStoreOrder(StoreOrderSaveReqVO updateReqVO) {
        // 校验存在
        validateStoreOrderExists(updateReqVO.getOrderId());
        // 更新
        StoreOrderDO updateObj = BeanUtils.toBean(updateReqVO, StoreOrderDO.class);
        storeOrderMapper.updateById(updateObj);
    }

    @Override
    public void deleteStoreOrder(Integer id) {
        // 校验存在
        validateStoreOrderExists(id);
        // 删除
        storeOrderMapper.deleteById(id);
    }

    private void validateStoreOrderExists(Integer id) {
        if (storeOrderMapper.selectById(id) == null) {
            throw exception(STORE_ORDER_NOT_EXISTS);
        }
    }

    @Override
    public StoreOrderDO getStoreOrder(Integer id) {
        return storeOrderMapper.selectById(id);
    }

    @Override
    public PageResult<StoreOrderDO> getStoreOrderPage(StoreOrderPageReqVO pageReqVO) {
        if(StrUtil.isNotBlank(pageReqVO.getMobile())){
            List<MemberUserDO> listByMobile = userService.getListByMobile(pageReqVO.getMobile());
            if(CollectionUtil.isNotEmpty(listByMobile)){
                List<Long> collect = listByMobile.stream().map(MemberUserDO::getId).collect(Collectors.toList());
                pageReqVO.setUserIds(collect);
            }else {
                return new PageResult<>();
            }

        }
        return storeOrderMapper.selectPage(pageReqVO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public StoreOrderDO createOrder(StoreOrderDto dto,Integer status) {
        StoreOrderDO storeOrderDO = new StoreOrderDO();
        Long storeId = cashregisterinfoApi.getStoreId(dto.getEquipmentCode());
        BeanUtil.copyProperties(dto, storeOrderDO);
        List<StoreGoodsDto> equipmentGoodsCustoms = dto.getEquipmentGoodsCustoms();
        double sum = equipmentGoodsCustoms.stream()
                .mapToDouble(StoreGoodsDto::getTotalPrice)
                .sum();
        storeOrderDO.setOriginalPrice(sum);
        storeOrderDO.setTotalPrice(sum);
        //计算折扣
        StoreDiscountDO storeDiscount = storeDiscountService.getStoreDiscountByStoreId(storeId);
        if(storeDiscount != null){
            BigDecimal discountNum = storeDiscount.getDiscountNum();
            BigDecimal totalMoney = new BigDecimal(sum).multiply(discountNum).divide(new BigDecimal(10), 2, RoundingMode.HALF_UP);
            storeOrderDO.setTotalPrice(totalMoney.doubleValue());
            storeOrderDO.setDiscountNum(discountNum);
        }

        storeOrderDO.setStatus(status);

        storeOrderDO.setCarteenId(storeId);
        storeOrderMapper.insert(storeOrderDO);
        ArrayList<StoreOrderDetailDO> detailDOS = new ArrayList<>();
        for (StoreGoodsDto storeGoodsDto : equipmentGoodsCustoms) {
            StoreOrderDetailDO storeOrderDetailDO = new StoreOrderDetailDO();
            BeanUtil.copyProperties(storeGoodsDto, storeOrderDetailDO);
            storeOrderDetailDO.setOrderId(storeOrderDO.getOrderId());
            detailDOS.add(storeOrderDetailDO);
        }
        orderDetailService.saveBatch(detailDOS);
        return storeOrderDO;
    }

    @Override
    public UserInfoVo facePay(FacePayDto dto) {
        StoreOrderDO storeOrderDO = storeOrderMapper.selectById(dto.getOrderId());
        storeOrderDO.setOpenId(dto.getOpenId());
        storeOrderMapper.updateById(storeOrderDO);
        Double totalPrice = storeOrderDO.getTotalPrice();
        BigDecimal total = BigDecimal.valueOf(totalPrice).setScale(2, RoundingMode.HALF_UP);
        MemberUserDO userDO = userService.getByFaceId(Long.valueOf(dto.getOpenId()));
        BigDecimal compute = compute(total, userDO.getId(), storeOrderDO.getCarteenId());
        UserInfoVo userInfoVo = new UserInfoVo();
        userInfoVo.setUserName(userDO.getNickname());
        userInfoVo.setAvatar("https://yclhit.com:8896" + userDO.getAvatar());
        userInfoVo.setBalance(compute.doubleValue());
        return userInfoVo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String cardPay(StoreOrderDto dto) {
        Long storeId = cashregisterinfoApi.getStoreId(dto.getEquipmentCode());
        MemberUserDO userDO = userService.getByCardId(dto.getCardNumber());
        if (ObjectUtil.isEmpty(userDO)) {
            return "该卡未绑定用户";
        }
        dto.setUserId(userDO.getId());
        Double totalPrice = createOrder(dto, StoreOrderStatusEnum.COMPLETE.getCode()).getTotalPrice();
        BigDecimal total = BigDecimal.valueOf(totalPrice).setScale(2, RoundingMode.HALF_UP);

        BigDecimal compute = compute(total, userDO.getId(),storeId);
        if (compute.compareTo(BigDecimal.ZERO) < 0) {
            return "false";
        } else {
            return "true";
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AddReqVO codePay(StoreOrderDto dto) {

        String s = storeOrderRedisTemplate.opsForValue().get(dto.getJwt());
        if (StrUtil.isBlank(s)) {
            throw exception(CODE_NOT_TIME);
        }
        Long storeId = cashregisterinfoApi.getStoreId(dto.getEquipmentCode());


        List<StoreGoodsDto> equipmentGoodsCustoms = dto.getEquipmentGoodsCustoms();
        double sum = equipmentGoodsCustoms.stream()
                .mapToDouble(StoreGoodsDto::getTotalPrice)
                .sum();

        BigDecimal totalMoney = BigDecimal.valueOf(sum);

        //计算折扣
        StoreDiscountDO storeDiscount = storeDiscountService.getStoreDiscountByStoreId(storeId);
        if(storeDiscount != null){
            BigDecimal discountNum = storeDiscount.getDiscountNum();
            totalMoney = new BigDecimal(sum).multiply(discountNum).divide(new BigDecimal(10), 2, RoundingMode.HALF_UP);
        }
        MemberUserDO user = userService.getUser(Long.valueOf(s));

        dto.setUserId(user.getId());
        checkMoney(user,totalMoney);

        //库存处理，扣除库存
        AddReqVO addReqVO = new AddReqVO();
        addReqVO.setType(InventoryTypeEnum.OUT.getCode());
        addReqVO.setOutType(OutTypeEnum.SELL.getCode());
        List<GoodsInfoReqVO> infos = new ArrayList<>();
        for (StoreGoodsDto detail : dto.getEquipmentGoodsCustoms()){
            if(detail.getGoodsId() == null){
                continue;
            }
            GoodsInfoReqVO vo = new GoodsInfoReqVO();
            BeanUtil.copyProperties(detail,vo);
            vo.setCarteenId(storeId);
            vo.setWeight(0d);
            infos.add(vo);
        }
        addReqVO.setList(infos);
        if(CollectionUtil.isNotEmpty(infos)){
            storeGoodsInventoryService.createStoreGoodsInventory(addReqVO);
        }

        StoreOrderDO order = createOrder(dto,StoreOrderStatusEnum.COMPLETE.getCode());
        Double totalPrice = order.getTotalPrice();
        BigDecimal total = BigDecimal.valueOf(totalPrice).setScale(2, RoundingMode.HALF_UP);

        BigDecimal compute = compute(total, user.getId(),storeId);
        if (compute.compareTo(BigDecimal.ZERO) < 0) {
            storeOrderMapper.deleteById(order.getOrderId());
            orderDetailService.deleteByOrderNo(order.getOrderId());
            throw exception(AMOUNT_NOT_ENOUGH);
        }
        //营业数据
        StatisticsVo statisticsVo = new StatisticsVo();
        statisticsVo.setCarteenId(order.getCarteenId());
        statisticsVo.setTotalMoney(total);
        statisticsVo.setOrderSum(1);
        statisticsVo.setTime(order.getCreateTime());
        statisticsVo.setOrderId(order.getOrderId().longValue());
        storeBusinessService.updateStatistics(statisticsVo);

        return addReqVO;
    }

    @Override
    public void batchCacheOrder(StoreOrderUploadDto dto) {
        for (StoreLocalOrderDto orderDto : dto.getMgcrCacheOrderVoList()) {
            StoreOrderDO storeOrderDO = new StoreOrderDO();
            BeanUtil.copyProperties(orderDto, storeOrderDO, "createTime");
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            storeOrderDO.setCreateTime(LocalDateTime.parse(orderDto.getCreateTime(), formatter));

            List<StoreGoodsDto> equipmentGoodsCustoms = orderDto.getEquipmentGoodsCustoms();
            double sum = equipmentGoodsCustoms.stream()
                    .mapToDouble(StoreGoodsDto::getTotalPrice)
                    .sum();
            storeOrderDO.setTotalPrice(sum);
            storeOrderMapper.insert(storeOrderDO);
            ArrayList<StoreOrderDetailDO> detailDOS = new ArrayList<>();
            for (StoreGoodsDto storeGoodsDto : equipmentGoodsCustoms) {
                StoreOrderDetailDO storeOrderDetailDO = new StoreOrderDetailDO();
                BeanUtil.copyProperties(storeGoodsDto, storeOrderDetailDO);
                storeOrderDetailDO.setOrderId(storeOrderDO.getOrderId());
                detailDOS.add(storeOrderDetailDO);
            }
            orderDetailService.saveBatch(detailDOS);
        }
        //todo:订单结算
    }

    public BigDecimal compute(BigDecimal total, Long userId,Long storeId) {
        return deductionService.storeDeduction(total, userId,storeId);
    }

    @Override
    public PageResult<StoreOrderPageVO> getStoreOrderPageNew(StoreOrderPageVO pageReqVO) {
        Page<StoreOrderPageVO> page = Page.of(pageReqVO.getPageNo(), pageReqVO.getPageSize());
        IPage<StoreOrderPageVO> pageNew = storeOrderMapper.getStoreOrderPageNew(page, pageReqVO);
        List<StoreOrderPageVO> records = pageNew.getRecords();
        return new PageResult<>(records, pageNew.getTotal());
    }

    @Override
    public List<StoreOrderPageVO> getStoreOrderPageNewList(StoreOrderPageVO pageReqVO) {
        return storeOrderMapper.getStoreOrderPageNewList(pageReqVO);
    }

    @Override
    public void reduction(Long orderId, BigDecimal money) {
        StoreOrderDO storeOrderDO = storeOrderMapper.selectById(orderId);
        Double totalPrice = storeOrderDO.getTotalPrice();
        BigDecimal total = BigDecimal.valueOf(totalPrice).setScale(2, RoundingMode.HALF_UP);
        if(total.compareTo(money) < 0){
            throw exception(ORDER_MONEY_NOT_ENOUGH);
        }
        Double reductionPrice = storeOrderDO.getReductionPrice();
        BigDecimal reduction = BigDecimal.valueOf(reductionPrice).setScale(2, RoundingMode.HALF_UP);
        storeOrderDO.setReductionPrice(reduction.add(money).doubleValue());
        storeOrderDO.setTotalPrice(total.subtract(money).doubleValue());
        storeOrderMapper.updateById(storeOrderDO);
        deductionService.reduction(storeOrderDO.getUserId(), money, BigDecimal.ZERO,money, BigDecimal.ZERO, storeOrderDO.getCarteenId());
        //营业数据
        StatisticsVo statisticsVo = new StatisticsVo();
        statisticsVo.setCarteenId(storeOrderDO.getCarteenId());
        statisticsVo.setTotalMoney(money.negate());
        statisticsVo.setOrderSum(0);
        statisticsVo.setReduceMoney(money);
        statisticsVo.setTime(storeOrderDO.getCreateTime());
        storeBusinessService.updateStatistics(statisticsVo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AddReqVO appCreate(CardDto dto) {
        MemberUserDO user = userService.getUser(dto.getUserId());
        BigDecimal total = BigDecimal.valueOf(dto.getTotalPrice());

        //计算折扣
        BigDecimal discountNum = null;
        StoreDiscountDO storeDiscount = storeDiscountService.getStoreDiscountByStoreId(dto.getCarteenId());
        if(storeDiscount != null){
            discountNum = storeDiscount.getDiscountNum();
            total = BigDecimal.valueOf(dto.getTotalPrice()).multiply(discountNum).divide(new BigDecimal(10), 2, RoundingMode.HALF_UP);
        }


        checkMoney(user,total);
        //扣除库存
        AddReqVO addReqVO = new AddReqVO();
        addReqVO.setType(InventoryTypeEnum.OUT.getCode());
        addReqVO.setOutType(OutTypeEnum.SELL.getCode());
        List<GoodsInfoReqVO> infos = new ArrayList<>();
        for (AppStoreGoodsDetail detail : dto.getGoodsList()){
            GoodsInfoReqVO vo = new GoodsInfoReqVO();
            BeanUtil.copyProperties(detail,vo);
            vo.setCarteenId(dto.getCarteenId());
            infos.add(vo);
        }
        addReqVO.setList(infos);
        storeGoodsInventoryService.createStoreGoodsInventory(addReqVO);

        //创建订单
        StoreOrderDO storeOrderDO = new StoreOrderDO();
        BeanUtil.copyProperties(dto, storeOrderDO);
        storeOrderDO.setOriginalPrice(dto.getTotalPrice());
        storeOrderDO.setTotalPrice(total.doubleValue());
        if(storeDiscount != null){
            storeOrderDO.setDiscountNum(storeDiscount.getDiscountNum());
        }

        storeOrderDO.setStatus(StoreOrderStatusEnum.PAY.getCode());
        storeOrderMapper.insert(storeOrderDO);
        List<AppStoreGoodsDetail> goodsList = dto.getGoodsList();
        ArrayList<StoreOrderDetailDO> addList = new ArrayList<>();
        for(AppStoreGoodsDetail goodsDetail : goodsList){
            StoreOrderDetailDO storeOrderDetailDO = new StoreOrderDetailDO();
            BeanUtil.copyProperties(goodsDetail, storeOrderDetailDO);
            storeOrderDetailDO.setOrderId(storeOrderDO.getOrderId());
            addList.add(storeOrderDetailDO);
        }
        orderDetailService.saveBatch(addList);

        //扣款
        BigDecimal compute = compute(total, dto.getUserId(),dto.getCarteenId());
        if (compute.compareTo(BigDecimal.ZERO) < 0) {
            storeOrderMapper.deleteById(storeOrderDO.getOrderId());
            orderDetailService.deleteByOrderNo(storeOrderDO.getOrderId());
            throw exception(AMOUNT_NOT_ENOUGH);
        }

        //删购物车
        List<Long> collect = goodsList.stream().map(AppStoreGoodsDetail::getCartId).collect(Collectors.toList());
        storeShoppingCartService.deleteBatch(collect);

        //营业数据
        StatisticsVo statisticsVo = new StatisticsVo();
        statisticsVo.setCarteenId(storeOrderDO.getCarteenId());
        statisticsVo.setTotalMoney(BigDecimal.valueOf(storeOrderDO.getTotalPrice()));
        statisticsVo.setOrderSum(1);
        statisticsVo.setTime(storeOrderDO.getCreateTime());
        statisticsVo.setOrderId(storeOrderDO.getOrderId().longValue());
        storeBusinessService.updateStatistics(statisticsVo);
        return addReqVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void customize(StoreOrderCustomizeVO dto) {

        MemberUserDO user = userService.getUserByMobile(dto.getJwt());

        List<StoreGoodsDto> equipmentGoodsCustoms = dto.getEquipmentGoodsCustoms();
        double sum = equipmentGoodsCustoms.stream()
                .mapToDouble(StoreGoodsDto::getTotalPrice)
                .sum();
        BigDecimal totalMoney = BigDecimal.valueOf(sum);
        dto.setUserId(user.getId());
        checkMoney(user,totalMoney);

        //创建订单
        StoreOrderDO storeOrderDO = new StoreOrderDO();
        BeanUtil.copyProperties(dto, storeOrderDO);

        //时间处理
        String type = dto.getType();
        String date = dto.getDate();
        if(CostTypeEnum.MORNING.getCode().equals(type)){
            date = date+" 08:00:00";
        }else if (CostTypeEnum.NOON.getCode().equals(type)){
            date = date+" 12:00:00";
        }else if (CostTypeEnum.NIGHT.getCode().equals(type)){
            date = date+" 17:00:00";
        }
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime now = LocalDateTime.parse(date, formatter);

        storeOrderDO.setStatus(StoreOrderStatusEnum.COMPLETE.getCode());
        storeOrderDO.setTotalPrice(sum);
        storeOrderDO.setCarteenId(dto.getCarteenId());
        storeOrderDO.setCreateTime(now);
        storeOrderMapper.insert(storeOrderDO);
        ArrayList<StoreOrderDetailDO> detailDOS = new ArrayList<>();
        for (StoreGoodsDto storeGoodsDto : equipmentGoodsCustoms) {
            StoreOrderDetailDO storeOrderDetailDO = new StoreOrderDetailDO();
            BeanUtil.copyProperties(storeGoodsDto, storeOrderDetailDO);
            storeOrderDetailDO.setOrderId(storeOrderDO.getOrderId());
            detailDOS.add(storeOrderDetailDO);
        }
        orderDetailService.saveBatch(detailDOS);

        BigDecimal total = BigDecimal.valueOf(sum).setScale(2, RoundingMode.HALF_UP);

        BigDecimal compute = compute(total, user.getId(),dto.getCarteenId());
        if (compute.compareTo(BigDecimal.ZERO) < 0) {
            storeOrderMapper.deleteById(storeOrderDO.getOrderId());
            orderDetailService.deleteByOrderNo(storeOrderDO.getOrderId());
            throw exception(AMOUNT_NOT_ENOUGH);
        }
        //营业数据
        StatisticsVo statisticsVo = new StatisticsVo();
        statisticsVo.setCarteenId(storeOrderDO.getCarteenId());
        statisticsVo.setTotalMoney(total);
        statisticsVo.setOrderSum(1);
        statisticsVo.setTime(storeOrderDO.getCreateTime());
        statisticsVo.setOrderId(storeOrderDO.getOrderId().longValue());
        storeBusinessService.updateStatistics(statisticsVo);
    }

    @Override
    public String code(Integer orderId) {
        StoreOrderDO storeOrderDO = storeOrderMapper.selectById(orderId);
        if(!storeOrderDO.getStatus().equals(StoreOrderStatusEnum.PAY.getCode())){
            return null;
        }
        return QRCodeWithJWTUtil.generateQRCode(QRCodeWithJWTUtil.QR_PREFIX_HX+orderId.toString(), 350, 350, null);// 生
    }

    @Override
    public AppStoreOrderVO info(String code) {
        code  = code.replace(QRCodeWithJWTUtil.QR_PREFIX_HX,"");
        Integer orderId = Integer.valueOf(code);
        StoreOrderDO storeOrderDO = storeOrderMapper.selectById(orderId);
        AppStoreOrderVO vo = new AppStoreOrderVO();
        BeanUtil.copyProperties(storeOrderDO,vo);
        List<StoreOrderDetailDO> listByOrderId = orderDetailService.getListByOrderId(orderId);
        vo.setGoodsList(listByOrderId);
        return vo;
    }

    @Override
    public Boolean complete(Integer orderId) {
        StoreOrderDO storeOrderDO = storeOrderMapper.selectById(orderId);
        if(ObjectUtil.isEmpty(storeOrderDO)){
            throw exception(STORE_ORDER_NOT_EXISTS);
        }
        if(!storeOrderDO.getStatus().equals(StoreOrderStatusEnum.PAY.getCode())){
            throw exception(STATUS_ERROR_ONE);
        }
        storeOrderDO.setStatus(StoreOrderStatusEnum.COMPLETE.getCode());
        storeOrderMapper.updateById(storeOrderDO);

        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AddReqVO cancel(Integer orderId) {
        StoreOrderDO storeOrderDO;
        synchronized (getStoreOrderLock(LockManager.CANCEL_KEY)) {
            storeOrderDO = storeOrderMapper.selectById(orderId);
            if(ObjectUtil.isEmpty(storeOrderDO)){
                throw exception(STORE_ORDER_NOT_EXISTS);
            }
            if(storeOrderDO.getStatus().equals(StoreOrderStatusEnum.COMPLETE.getCode())
                    || storeOrderDO.getStatus().equals(StoreOrderStatusEnum.REFUND.getCode())){
                throw exception(STATUS_ERROR);
            }
            if(storeOrderDO.getStatus().equals(StoreOrderStatusEnum.CANCEL.getCode())){
                throw exception(STATUS_ERROR_CANCEL);
            }
        }

        //修改状态
        storeOrderDO.setStatus(StoreOrderStatusEnum.CANCEL.getCode());
        storeOrderMapper.updateById(storeOrderDO);

        //退款
        deductionService.reduction(storeOrderDO.getUserId(),BigDecimal.valueOf(storeOrderDO.getTotalPrice())
                ,BigDecimal.ZERO,BigDecimal.valueOf(storeOrderDO.getTotalPrice()),BigDecimal.ZERO, storeOrderDO.getCarteenId());

        //更新库存
        List<StoreOrderDetailDO> listByOrderId = orderDetailService.getListByOrderId(storeOrderDO.getOrderId());

        AddReqVO addReqVO = new AddReqVO();
        addReqVO.setType(InventoryTypeEnum.IN.getCode());
        addReqVO.setOutType(OutTypeEnum.ORDER_ADD.getCode());
        List<GoodsInfoReqVO> infos = new ArrayList<>();
        for (StoreOrderDetailDO detail : listByOrderId){
            GoodsInfoReqVO vo = new GoodsInfoReqVO();
            BeanUtil.copyProperties(detail,vo);
            vo.setCarteenId(storeOrderDO.getCarteenId());
            infos.add(vo);
        }
        addReqVO.setList(infos);
        storeGoodsInventoryService.createStoreGoodsInventory(addReqVO);

        //营业数据
        StatisticsVo statisticsVo = new StatisticsVo();
        statisticsVo.setCarteenId(storeOrderDO.getCarteenId());
        statisticsVo.setTotalMoney(BigDecimal.valueOf(storeOrderDO.getTotalPrice()).negate());
        statisticsVo.setOrderSum(-1);
        statisticsVo.setTime(storeOrderDO.getCreateTime());
        statisticsVo.setOrderId(storeOrderDO.getOrderId().longValue());
        storeBusinessService.updateStatistics(statisticsVo);

        return addReqVO;
    }

    @Override
    public Long refund(Integer orderId) {

        StoreOrderDO storeOrderDO = storeOrderMapper.selectById(orderId);
        if(ObjectUtil.isEmpty(storeOrderDO)){
            throw exception(STORE_ORDER_NOT_EXISTS);
        }
        if(storeOrderDO.getStatus().equals(StoreOrderStatusEnum.COMPLETE.getCode())
                || storeOrderDO.getStatus().equals(StoreOrderStatusEnum.REFUND.getCode())){
            throw exception(STATUS_ERROR);
        }
        StoreRefundSaveReqVO storeRefundSaveReqVO = new StoreRefundSaveReqVO();
        storeRefundSaveReqVO.setOrderId(storeOrderDO.getOrderId());
        storeRefundSaveReqVO.setStatus(RefundStatusEnum.TO_AUDIT.getCode());
        storeRefundSaveReqVO.setCarteenId(storeOrderDO.getCarteenId());
        storeRefundSaveReqVO.setOrderMoney(BigDecimal.valueOf(storeOrderDO.getTotalPrice()));

        MemberUserDO user = userService.getUser(storeOrderDO.getUserId());
        storeRefundSaveReqVO.setUserId(storeOrderDO.getUserId());
        storeRefundSaveReqVO.setUserName(user.getNickname());
        storeRefundSaveReqVO.setMobile(user.getMobile());

        return storeRefundService.createStoreRefund(storeRefundSaveReqVO);
    }

    @Override
    public List<StoreOrderDO> selectPayOrder() {
        return storeOrderMapper.selectList(Wrappers.<StoreOrderDO>lambdaQuery()
                .eq(StoreOrderDO::getStatus,StoreOrderStatusEnum.PAY.getCode()));
    }

    @Override
    public AddReqVO refundAdmin(Integer orderId) {
        StoreOrderDO storeOrderDO;
        synchronized (getStoreOrderLock(LockManager.CANCEL_KEY)) {
            storeOrderDO = storeOrderMapper.selectById(orderId);
            if(ObjectUtil.isEmpty(storeOrderDO)){
                throw exception(STORE_ORDER_NOT_EXISTS);
            }
            if( storeOrderDO.getStatus().equals(StoreOrderStatusEnum.REFUND.getCode())){
                throw exception(STATUS_ERROR_REFUND);
            }
            if(storeOrderDO.getStatus().equals(StoreOrderStatusEnum.CANCEL.getCode())){
                throw exception(STATUS_ERROR_CANCEL);
            }
        }

        //修改状态
        storeOrderDO.setStatus(StoreOrderStatusEnum.REFUND.getCode());
        storeOrderMapper.updateById(storeOrderDO);

        //退款
        deductionService.reduction(storeOrderDO.getUserId(),BigDecimal.valueOf(storeOrderDO.getTotalPrice())
                ,BigDecimal.ZERO,BigDecimal.valueOf(storeOrderDO.getTotalPrice()),BigDecimal.ZERO, storeOrderDO.getCarteenId());

        //更新库存
        List<StoreOrderDetailDO> listByOrderId = orderDetailService.getListByOrderId(storeOrderDO.getOrderId());

        AddReqVO addReqVO = new AddReqVO();
        addReqVO.setType(InventoryTypeEnum.IN.getCode());
        addReqVO.setOutType(OutTypeEnum.ORDER_ADD.getCode());
        List<GoodsInfoReqVO> infos = new ArrayList<>();
        for (StoreOrderDetailDO detail : listByOrderId){
            GoodsInfoReqVO vo = new GoodsInfoReqVO();
            BeanUtil.copyProperties(detail,vo);
            vo.setCarteenId(storeOrderDO.getCarteenId());
            vo.setWeight(0D);
            infos.add(vo);
        }
        addReqVO.setList(infos);
        storeGoodsInventoryService.createStoreGoodsInventory(addReqVO);

        //营业数据
        StatisticsVo statisticsVo = new StatisticsVo();
        statisticsVo.setCarteenId(storeOrderDO.getCarteenId());
        statisticsVo.setTotalMoney(BigDecimal.valueOf(storeOrderDO.getTotalPrice()).negate());
        statisticsVo.setOrderSum(-1);
        statisticsVo.setTime(storeOrderDO.getCreateTime());
        statisticsVo.setOrderId(storeOrderDO.getOrderId().longValue());
        storeBusinessService.updateStatistics(statisticsVo);

        return addReqVO;
    }

    @Override
    public void completeList(List<Integer> orderIds) {
        for (Integer orderId : orderIds){
            StoreOrderDO storeOrderDO = storeOrderMapper.selectById(orderId);
            if(ObjectUtil.isEmpty(storeOrderDO)){
                continue;
            }
            if(storeOrderDO.getStatus().equals(StoreOrderStatusEnum.PAY.getCode())){
                storeOrderDO.setStatus(StoreOrderStatusEnum.COMPLETE.getCode());
                storeOrderMapper.updateById(storeOrderDO);
            }else {
                //扣款
                deductionService.storeDeduction(BigDecimal.valueOf(storeOrderDO.getTotalPrice()), storeOrderDO.getUserId(),storeOrderDO.getCarteenId());
                //营业数据
                StatisticsVo statisticsVo = new StatisticsVo();
                statisticsVo.setCarteenId(storeOrderDO.getCarteenId());
                statisticsVo.setTotalMoney(BigDecimal.valueOf(storeOrderDO.getTotalPrice()));
                statisticsVo.setOrderSum(1);
                statisticsVo.setTime(storeOrderDO.getCreateTime());
                statisticsVo.setOrderId(storeOrderDO.getOrderId().longValue());
                storeBusinessService.updateStatistics(statisticsVo);
            }


        }
    }

    @Override
    public List<StoreOrderCountVO> countOrder(String startTime, String endTime) {
        return storeOrderMapper.countOrder(startTime,endTime);
    }

    @Override
    public BigDecimal getDiscount(String equipmentCode) {
        Long storeId = cashregisterinfoApi.getStoreId(equipmentCode);
        //计算折扣
        StoreDiscountDO storeDiscount = storeDiscountService.getStoreDiscountByStoreId(storeId);
        if(storeDiscount == null){
            return null;
        }
        return storeDiscount.getDiscountNum().divide(BigDecimal.valueOf(10), 2, RoundingMode.HALF_UP);
    }

    public void checkMoney(MemberUserDO user, BigDecimal totalMoney) {
        //获取用户所在组分类
        BigDecimal computeMoney = user.getMoney();
        if (MemberConstants.LIMIT_SWITCH) {
            List<Integer> types = memberGroupService.getGroupTypeListByUserId(user.getId());
            if (types.contains(GroupTypeEnum.YCLH.getCode()) || types.contains(GroupTypeEnum.DISTRICT.getCode())) {
                computeMoney = user.getWxAmount();
            }
        }

        if (computeMoney.compareTo(totalMoney) < 0) {
            throw exception(AMOUNT_NOT_ENOUGH);
        }

    }

}