package com.yiqi.api.controller.order;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
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.plugins.pagination.Page;
import com.yiqi.app.domain.AppUser;
import com.yiqi.app.domain.AppUserAddress;
import com.yiqi.app.domain.vo.AppUserVO;
import com.yiqi.app.service.IAppUserAddressService;
import com.yiqi.app.service.IAppUserBillMstrService;
import com.yiqi.app.service.IAppUserService;
import com.yiqi.common.constant.UrlConstants;
import com.yiqi.common.core.domain.AuthHolder;
import com.yiqi.common.core.domain.BaseEntity;
import com.yiqi.common.core.domain.R;
import com.yiqi.common.enums.*;
import com.yiqi.common.utils.*;
import com.yiqi.order.domain.OrderCloth;
import com.yiqi.order.domain.OrderClothItem;
import com.yiqi.order.domain.OrderDelivery;
import com.yiqi.order.domain.dto.OrderClothAppPayDTO;
import com.yiqi.order.domain.dto.OrderClothAppointmentDTO;
import com.yiqi.order.domain.dto.OrderClothPayDTO;
import com.yiqi.order.domain.dto.weapp.OrderClothAppQueryDTO;
import com.yiqi.order.domain.dto.weapp.UpdateOrderClothTakeClothWayDTO;
import com.yiqi.order.domain.dto.weapp.WeAppOrderClothAppointmentQueryDTO;
import com.yiqi.order.domain.vo.OrderClothVO;
import com.yiqi.order.domain.vo.OrderPayResultVO;
import com.yiqi.order.domain.vo.weapp.WeAppOrderClothAppointmentVO;
import com.yiqi.order.service.*;
import com.yiqi.system.domain.SysOrg;
import com.yiqi.system.domain.SysStore;
import com.yiqi.system.service.ISysConfigService;
import com.yiqi.system.service.ISysOrgService;
import com.yiqi.system.service.ISysStoreService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author xiaohei
 * @date 2023/10/6
 */
@Api(tags = "洗衣订单")
@RestController
@RequestMapping(value = UrlConstants.wxappApi + "/order")
public class WeAppOrderClothController {

    @Autowired
    private IOrderClothService orderClothService;
    @Autowired
    private IAppUserAddressService appUserAddressService;
    @Autowired
    private ISysOrgService sysOrgService;
    @Autowired
    private ISysStoreService storeService;
    @Autowired
    private IOrderClothItemService orderClothItemService;
    @Autowired
    private IOrderClothItemFlowRecordService orderClothItemFlowRecordService;
    @Autowired
    private IOrderDeliveryService orderDeliveryService;
    @Autowired
    private OrderNoUtils orderNoUtils;
    @Autowired
    private ISysConfigService sysConfigService;
    @Autowired
    private IAppUserBillMstrService appUserBillMstrService;
    @Autowired
    private IPayService payService;
    @Autowired
    private IAppUserService appUserService;

    @ApiOperation("获取预约洗送列表")
    @PostMapping(value = "findAppointmentPage")
    public R<List<WeAppOrderClothAppointmentVO>> findAppointmentPage(@RequestBody @Valid WeAppOrderClothAppointmentQueryDTO weAppOrderClothAppointmentQueryDTO)
            throws Exception {
        Page<OrderCloth> page = new Page<>(weAppOrderClothAppointmentQueryDTO.getPageNum(), weAppOrderClothAppointmentQueryDTO.getPageSize());
        page.setSearchCount(false);

        LambdaQueryWrapper<OrderCloth> queryWrapper = new QueryWrapper<OrderCloth>().lambda()
                .eq(OrderCloth::getAppUserId, AuthHolder.userId())
                .eq(OrderCloth::getRefundStatus, OrderRefundStatus.OK.getCode())
                .and(orderClothLambdaQueryWrapper -> orderClothLambdaQueryWrapper
                        .eq(OrderCloth::getTakeClothWay, TakeOrSendClothWay.DELIVERY.getCode())
                        .or()
                        .eq(OrderCloth::getSendClothWay, TakeOrSendClothWay.DELIVERY.getCode())
                );
        if (StringUtils.isNotEmpty(weAppOrderClothAppointmentQueryDTO.getOrderStatus())) {
            //带上门
            if ("1".equals(weAppOrderClothAppointmentQueryDTO.getOrderStatus())) {
                queryWrapper.and(orderClothLambdaQueryWrapper -> orderClothLambdaQueryWrapper
                        .eq(OrderCloth::getOrderStatus, ClothOrderStatusType.APPOINTMENT.getCode())
                        .or()
                        .eq(OrderCloth::getOrderStatus, ClothOrderStatusType.WAITING_TO_DOOR.getCode())
                );
            }
            //已上门
            if ("2".equals(weAppOrderClothAppointmentQueryDTO.getOrderStatus())) {
                queryWrapper.and(orderClothLambdaQueryWrapper -> orderClothLambdaQueryWrapper
                        .eq(OrderCloth::getOrderStatus, ClothOrderStatusType.HAS_TO_DOOR.getCode())
                        .or()
                        .eq(OrderCloth::getOrderStatus, ClothOrderStatusType.HAS_TAKING.getCode())
                );
            }
            //已上门
            if ("8".equals(weAppOrderClothAppointmentQueryDTO.getOrderStatus())) {
                queryWrapper.and(orderClothLambdaQueryWrapper -> orderClothLambdaQueryWrapper
                        .eq(OrderCloth::getOrderStatus, ClothOrderStatusType.WAITING_FOR_HANG.getCode())
                );
            }
            //已上门
            if ("9".equals(weAppOrderClothAppointmentQueryDTO.getOrderStatus())) {
                queryWrapper.and(orderClothLambdaQueryWrapper -> orderClothLambdaQueryWrapper
                        .eq(OrderCloth::getOrderStatus, ClothOrderStatusType.WAITING_TO_SEND.getCode())
                        .or()
                        .eq(OrderCloth::getOrderStatus, ClothOrderStatusType.SENDING.getCode())
                );
            }
        }
        queryWrapper.orderByDesc(BaseEntity::getCreateTime);
        List<OrderCloth> orderCloths = orderClothService.page(page
                , queryWrapper).getRecords();
        if (orderCloths.size() == 0) {
            return R.ok(new ArrayList<>());
        }

        List<OrderDelivery> list = orderDeliveryService.list(new QueryWrapper<OrderDelivery>().lambda()
                .in(OrderDelivery::getOrderSn
                        , orderCloths.stream().map(OrderCloth::getOrderNo).collect(Collectors.toSet())));
        Map<String, OrderDelivery> collectAddressMap = list.stream().filter(orderDelivery -> ClothOrderDeliveryType.collectCloth.getCode()
                        .equals(orderDelivery.getClothOrderType()))
                .collect(Collectors.toMap(OrderDelivery::getOrderSn, OrderDelivery -> OrderDelivery));
        Map<String, OrderDelivery> takeAddressMap = list.stream().filter(orderDelivery -> ClothOrderDeliveryType.takeCloth.getCode()
                        .equals(orderDelivery.getClothOrderType()))
                .collect(Collectors.toMap(OrderDelivery::getOrderSn, OrderDelivery -> OrderDelivery));
        Map<Long, SysOrg> storeOrgMap = new HashMap<>();
        Map<Long, SysOrg> factoryOrgMap = new HashMap<>();
        if (orderCloths.stream().filter(orderCloth -> SourceType.STORE.getCode().equals(orderCloth.getSourceType())).collect(Collectors.toList()).size() > 0) {
            storeOrgMap = sysOrgService.list(new QueryWrapper<SysOrg>().lambda().in(SysOrg::getId
                            , orderCloths.stream().filter(orderCloth -> SourceType.STORE.getCode().equals(orderCloth.getSourceType())).map(OrderCloth::getOrgId).collect(Collectors.toSet()))
                    .eq(SysOrg::getSourceType, SourceType.STORE.getCode())).stream().collect(Collectors.toMap(SysOrg::getId, SysOrg -> SysOrg));
        }
        if (orderCloths.stream().filter(orderCloth -> SourceType.FACTORY.getCode().equals(orderCloth.getSourceType())).collect(Collectors.toList()).size() > 0) {
            factoryOrgMap = sysOrgService.list(new QueryWrapper<SysOrg>().lambda().in(SysOrg::getId
                            , orderCloths.stream().filter(orderCloth -> SourceType.FACTORY.getCode().equals(orderCloth.getSourceType())).map(OrderCloth::getOrgId).collect(Collectors.toSet()))
                    .eq(SysOrg::getSourceType, SourceType.FACTORY.getCode())).stream().collect(Collectors.toMap(SysOrg::getId, SysOrg -> SysOrg));
        }
        List<WeAppOrderClothAppointmentVO> weAppOrderClothAppointmentVOS = new ArrayList<>();
        for (OrderCloth orderCloth : orderCloths) {
            WeAppOrderClothAppointmentVO weAppOrderClothAppointmentVO = new WeAppOrderClothAppointmentVO();
            BeanUtils.copyProperties(orderCloth, weAppOrderClothAppointmentVO);
            weAppOrderClothAppointmentVO.setCollectClothDeliverInfo(collectAddressMap.get(orderCloth.getId()));
            weAppOrderClothAppointmentVO.setTakeClothDeliverInfo(takeAddressMap.get(orderCloth.getId()));
            if (SourceType.FACTORY.getCode().equals(orderCloth.getSourceType())) {
                weAppOrderClothAppointmentVO.setSysOrg(factoryOrgMap.get(orderCloth.getOrgId()));
            } else if (SourceType.STORE.getCode().equals(orderCloth.getSourceType())) {
                weAppOrderClothAppointmentVO.setSysOrg(storeOrgMap.get(orderCloth.getOrgId()));
            } else {
                weAppOrderClothAppointmentVO.setSysOrg(SysOrg.buildManagerOrg());
            }
            weAppOrderClothAppointmentVOS.add(weAppOrderClothAppointmentVO);
        }
        return R.ok(weAppOrderClothAppointmentVOS);
    }

    @ApiOperation("预约洗衣")
    @PostMapping(value = "appointment")
    public R appointment(@RequestBody @Valid OrderClothAppointmentDTO orderClothAppointmentDTO) throws Exception {
        AppUserAddress appUserAddress = appUserAddressService.getOne(new QueryWrapper<AppUserAddress>().lambda()
                .eq(AppUserAddress::getId, orderClothAppointmentDTO.getAddressId())
                .eq(AppUserAddress::getAppUserId, AuthHolder.userId()));
        if (appUserAddress == null) {
            throw new ServiceException("未查询到地址");
        }
        OrderCloth orderCloth = new OrderCloth();
        BeanUtils.copyProperties(orderClothAppointmentDTO, orderCloth);
        orderCloth.setCreateTime(DateUtils.getNowDate());
        orderCloth.setTakeClothWay(TakeOrSendClothWay.DELIVERY.getCode());
        orderCloth.setAppUserId(AuthHolder.userId());
        orderCloth.setDelFlag(DeleteStatus.OK.getCode());
        orderCloth.setOrderStatus(ClothOrderStatusType.APPOINTMENT.getCode());
        orderCloth.setIsDisassemblyAndAssembly(StringUtils.isEmpty(orderClothAppointmentDTO.getIsDismountingAndAssembling()) ? SysBoolType.NO.getCode() : orderClothAppointmentDTO.getIsDismountingAndAssembling());
        // 预约单
        orderCloth.setIsAppointment(SysBoolType.YES.getCode());
        orderCloth.setOrderNo(orderNoUtils.getClothOrderNo());
        if (ClothOrderType.normal.equals(orderCloth.getOrderType())) {
            SysStore sysStore = storeService.selectSysStoreById(orderClothAppointmentDTO.getOrgId());
            orderCloth.setFactoryId(sysStore.getFactoryId());
        }

        //云洗订单或者第三方订单
        if (ClothOrderType.online.getCode().equals(orderCloth.getOrderType())
                || ClothOrderType.thirdPart.getCode().equals(orderCloth.getOrderType())) {
        }
        orderClothService.save(orderCloth);
        // 预创建配送单
        OrderDelivery orderDelivery = new OrderDelivery(appUserAddress);
        orderDelivery.buildCreateData();
        orderDelivery.setDeliverySn(orderNoUtils.getDeliveryOrderNo());
        orderDelivery.setOrderSn(orderCloth.getOrderNo());
        orderDelivery.setStoreId(orderCloth.getOrgId());
        orderDelivery.setClothOrderType(ClothOrderDeliveryType.collectCloth.getCode());
        orderDelivery.setCreateTime(DateUtils.getNowDate());
        orderDelivery.setDeliveryStatus(OrderDeliveryStatusEnum.WAIT_DELIVERY.getCode());
        orderDelivery.setDeliveryWay(ClothOrderDeliveryWay.delivery.getCode());
        orderDelivery.setStoreId(orderClothAppointmentDTO.getOrgId());
        orderDelivery.buildCreateData();
        orderDeliveryService.save(orderDelivery);
        return R.ok();
    }

    /**
     * @param orderClothAppQueryDTO
     * @return orderStatus 代付款 2、服务中-3、带取衣 6、待送达 8、 已完成 12
     * @throws Exception
     */
    @ApiOperation("查询洗衣订单列表")
    @PostMapping(value = "findPage")
    public R<List<OrderClothVO>> findPage(@RequestBody @Valid OrderClothAppQueryDTO orderClothAppQueryDTO) throws Exception {
        LambdaQueryWrapper<OrderCloth> queryWrapper = new QueryWrapper<OrderCloth>().lambda()
                .eq(OrderCloth::getAppUserId, AuthHolder.userId())
                .eq(OrderCloth::getDelFlag, DeleteStatus.OK.getCode());
        if (orderClothAppQueryDTO.getStartDate() != null) {
            queryWrapper.ge(BaseEntity::getCreateTime, orderClothAppQueryDTO.getStartDate());
        }
        if (orderClothAppQueryDTO.getEndDate() != null) {
            queryWrapper.lt(BaseEntity::getCreateTime, DateUtils.addDays(orderClothAppQueryDTO.getEndDate(), 1));
        }
        //2=待付款，3=服务中，4=待配送，5=配送中，6=待取衣（到店自取），7=待评价，8=已完成，100=已取消
        if ("2".equals(orderClothAppQueryDTO.getOrderStatus())) {
            queryWrapper.and(orderClothLambdaQueryWrapper -> orderClothLambdaQueryWrapper
                    .eq(OrderCloth::getPayStatus, PayStatus.WAITING_TO_PAY.getCode())
            );
        }
        if ("3".equals(orderClothAppQueryDTO.getOrderStatus())) {
            queryWrapper.and(orderClothLambdaQueryWrapper -> orderClothLambdaQueryWrapper
                    .eq(OrderCloth::getOrderStatus, ClothOrderStatusType.WAIT_FACTORY.getCode())
                    .or()
                    .eq(OrderCloth::getOrderStatus, ClothOrderStatusType.WASHING.getCode())
                    .or()
                    .eq(OrderCloth::getOrderStatus, ClothOrderStatusType.HAS_WASH.getCode())
            );

        }
        if ("6".equals(orderClothAppQueryDTO.getOrderStatus())) {
            queryWrapper.and(orderClothLambdaQueryWrapper -> orderClothLambdaQueryWrapper
                    .eq(OrderCloth::getOrderStatus, ClothOrderStatusType.WAITING_FOR_HANG.getCode()));
        }
        if ("8".equals(orderClothAppQueryDTO.getOrderStatus())) {
            queryWrapper.and(orderClothLambdaQueryWrapper -> orderClothLambdaQueryWrapper
                    .eq(OrderCloth::getOrderStatus, ClothOrderStatusType.WAITING_TO_SEND.getCode())
                    .or()
                    .eq(OrderCloth::getOrderStatus, ClothOrderStatusType.SENDING.getCode()));
        }
        if ("12".equals(orderClothAppQueryDTO.getOrderStatus())) {
            queryWrapper.and(orderClothLambdaQueryWrapper -> orderClothLambdaQueryWrapper
                    .eq(OrderCloth::getOrderStatus, ClothOrderStatusType.WAITING_FOR_COMMENT.getCode())
                    .or()
                    .eq(OrderCloth::getOrderStatus, ClothOrderStatusType.FINISH.getCode()));
        }

        queryWrapper.orderByDesc(BaseEntity::getCreateTime);
        List<OrderCloth> orderCloths = orderClothService.page(new Page<>(orderClothAppQueryDTO.getPageNum()
                , orderClothAppQueryDTO.getPageSize(), false), queryWrapper).getRecords();
        List<OrderClothVO> orderClothVOS = new ArrayList<>();
        if (orderCloths.size() == 0) {
            return R.ok(orderClothVOS);
        }

        Map<Long, AppUser> takeClothUserMap = new HashMap<>();
        if (orderCloths.stream().filter(orderCloth -> orderCloth.getTakeClothAppUserId() != null)
                .map(OrderCloth::getAppUserId).collect(Collectors.toSet()).size() > 0) {
            takeClothUserMap = appUserService.list(new QueryWrapper<AppUser>().lambda()
                            .in(AppUser::getId, orderCloths.stream().filter(orderCloth -> orderCloth.getTakeClothAppUserId() != null)
                                    .map(OrderCloth::getAppUserId).collect(Collectors.toSet())))
                    .stream().collect(Collectors.toMap(AppUser::getId, AppUser -> AppUser));
        }

        Map<Long, AppUser> sendClothUserMap = new HashMap<>();
        if (orderCloths.stream().filter(orderCloth -> orderCloth.getSendClothAppUserId() != null)
                .map(OrderCloth::getAppUserId).collect(Collectors.toSet()).size() > 0) {
            sendClothUserMap = appUserService.list(new QueryWrapper<AppUser>().lambda()
                            .in(AppUser::getId, orderCloths.stream().filter(orderCloth -> orderCloth.getSendClothAppUserId() != null)
                                    .map(OrderCloth::getAppUserId).collect(Collectors.toSet())))
                    .stream().collect(Collectors.toMap(AppUser::getId, AppUser -> AppUser));
        }
        Map<Long, SysOrg> storeOrgMap = new HashMap<>();
        Map<Long, SysOrg> factoryOrgMap = new HashMap<>();
        if (orderCloths.stream().filter(orderCloth -> SourceType.STORE.getCode()
                .equals(orderCloth.getSourceType())).collect(Collectors.toList()).size() > 0) {
            storeOrgMap = sysOrgService.list(new QueryWrapper<SysOrg>().lambda().eq(SysOrg::getSourceType
                            , SourceType.STORE.getCode()).in(SysOrg::getId, orderCloths.stream()
                            .map(OrderCloth::getOrgId).collect(Collectors.toSet()))).stream()
                    .collect(Collectors.toMap(SysOrg::getId, SysOrg -> SysOrg));
        }
        if (orderCloths.stream().filter(orderCloth -> SourceType.FACTORY.getCode()
                .equals(orderCloth.getSourceType())).collect(Collectors.toList()).size() > 0) {
            factoryOrgMap = sysOrgService.list(new QueryWrapper<SysOrg>().lambda().eq(SysOrg::getSourceType
                            , SourceType.FACTORY.getCode()).in(SysOrg::getId, orderCloths.stream()
                            .map(OrderCloth::getOrgId).collect(Collectors.toSet()))).stream()
                    .collect(Collectors.toMap(SysOrg::getId, SysOrg -> SysOrg));
        }
        for (OrderCloth record : orderCloths) {
            OrderClothVO orderClothVO = new OrderClothVO();
            BeanUtils.copyProperties(record, orderClothVO);
            if (record.getTakeClothAppUserId() != null && takeClothUserMap.containsKey(record.getTakeClothAppUserId())) {
                AppUserVO appUserVO = new AppUserVO();
                BeanUtils.copyProperties(takeClothUserMap.get(record.getTakeClothAppUserId()), appUserVO);
                orderClothVO.setTakeClothUserVO(appUserVO);
            }
            if (record.getSendClothAppUserId() != null && sendClothUserMap.containsKey(record.getSendClothAppUserId())) {
                AppUserVO appUserVO = new AppUserVO();
                BeanUtils.copyProperties(sendClothUserMap.get(record.getSendClothAppUserId()), appUserVO);
                orderClothVO.setSendClothUserVO(appUserVO);
            }
            if (SourceType.STORE.getCode().equals(orderClothVO.getSourceType())) {
                orderClothVO.setSysOrg(storeOrgMap.get(orderClothVO.getOrgId()));
            } else if (SourceType.FACTORY.getCode().equals(orderClothVO.getSourceType())) {
                orderClothVO.setSysOrg(factoryOrgMap.get(orderClothVO.getOrgId()));
            }
            orderClothVOS.add(orderClothVO);
        }
        return R.ok(orderClothVOS);
    }

    /**
     * 查询洗好送回订单列表
     * orderStatus : 8 : 已到店带取衣  9：待送衣   10：送衣中
     */
    @ApiOperation("查询洗好送回订单列表")
    @PostMapping(value = "findSendPage")
    public R<List<OrderClothVO>> findSendPage(@RequestBody @Valid OrderClothAppQueryDTO orderClothAppQueryDTO) throws Exception {
        LambdaQueryWrapper<OrderCloth> queryWrapper = new QueryWrapper<OrderCloth>().lambda()
                .eq(OrderCloth::getAppUserId, AuthHolder.userId())
                .eq(OrderCloth::getDelFlag, DeleteStatus.OK.getCode());
        if (orderClothAppQueryDTO.getStartDate() != null) {
            queryWrapper.ge(BaseEntity::getCreateTime, orderClothAppQueryDTO.getStartDate());
        }
        if (orderClothAppQueryDTO.getEndDate() != null) {
            queryWrapper.lt(BaseEntity::getCreateTime, DateUtils.addDays(orderClothAppQueryDTO.getEndDate(), 1));
        }
        //0=待上门，1=已上门、带门店定价，2=待付款，3=服务中，4=待配送，5=配送中，6=待取衣（到店自取），7=待评价，8=已完成，100=已取消
        if ("8".equals(orderClothAppQueryDTO.getOrderStatus())) {
            queryWrapper.and(orderClothLambdaQueryWrapper -> orderClothLambdaQueryWrapper
                    .eq(OrderCloth::getOrderStatus, ClothOrderStatusType.WAITING_FOR_HANG.getCode()));
        }
        if ("9".equals(orderClothAppQueryDTO.getOrderStatus())) {
            queryWrapper.and(orderClothLambdaQueryWrapper -> orderClothLambdaQueryWrapper
                    .eq(OrderCloth::getOrderStatus, ClothOrderStatusType.WAITING_TO_SEND.getCode()));
        }
        if ("10".equals(orderClothAppQueryDTO.getOrderStatus())) {
            queryWrapper.and(orderClothLambdaQueryWrapper -> orderClothLambdaQueryWrapper
                    .eq(OrderCloth::getOrderStatus, ClothOrderStatusType.SENDING.getCode()));
        }

        queryWrapper.orderByDesc(BaseEntity::getCreateTime);
        List<OrderCloth> orderCloths = orderClothService.page(new Page<>(orderClothAppQueryDTO.getPageNum()
                , orderClothAppQueryDTO.getPageSize(), false), queryWrapper).getRecords();
        List<OrderClothVO> orderClothVOS = new ArrayList<>();
        if (orderCloths.size() == 0) {
            return R.ok(orderClothVOS);
        }

        Map<Long, AppUser> takeClothUserMap = new HashMap<>();
        if (orderCloths.stream().filter(orderCloth -> orderCloth.getTakeClothAppUserId() != null)
                .map(OrderCloth::getAppUserId).collect(Collectors.toSet()).size() > 0) {
            takeClothUserMap = appUserService.list(new QueryWrapper<AppUser>().lambda()
                            .in(AppUser::getId, orderCloths.stream().filter(orderCloth -> orderCloth.getTakeClothAppUserId() != null)
                                    .map(OrderCloth::getAppUserId).collect(Collectors.toSet())))
                    .stream().collect(Collectors.toMap(AppUser::getId, AppUser -> AppUser));
        }

        Map<Long, AppUser> sendClothUserMap = new HashMap<>();
        if (orderCloths.stream().filter(orderCloth -> orderCloth.getSendClothAppUserId() != null)
                .map(OrderCloth::getAppUserId).collect(Collectors.toSet()).size() > 0) {
            sendClothUserMap = appUserService.list(new QueryWrapper<AppUser>().lambda()
                            .in(AppUser::getId, orderCloths.stream().filter(orderCloth -> orderCloth.getSendClothAppUserId() != null)
                                    .map(OrderCloth::getAppUserId).collect(Collectors.toSet())))
                    .stream().collect(Collectors.toMap(AppUser::getId, AppUser -> AppUser));
        }
        Map<Long, SysOrg> storeOrgMap = new HashMap<>();
        Map<Long, SysOrg> factoryOrgMap = new HashMap<>();
        if (orderCloths.stream().filter(orderCloth -> SourceType.STORE.getCode()
                .equals(orderCloth.getSourceType())).collect(Collectors.toList()).size() > 0) {
            storeOrgMap = sysOrgService.list(new QueryWrapper<SysOrg>().lambda().eq(SysOrg::getSourceType
                            , SourceType.STORE.getCode()).in(SysOrg::getId, orderCloths.stream()
                            .map(OrderCloth::getOrgId).collect(Collectors.toSet()))).stream()
                    .collect(Collectors.toMap(SysOrg::getId, SysOrg -> SysOrg));
        }
        if (orderCloths.stream().filter(orderCloth -> SourceType.FACTORY.getCode()
                .equals(orderCloth.getSourceType())).collect(Collectors.toList()).size() > 0) {
            factoryOrgMap = sysOrgService.list(new QueryWrapper<SysOrg>().lambda().eq(SysOrg::getSourceType
                            , SourceType.FACTORY.getCode()).in(SysOrg::getId, orderCloths.stream()
                            .map(OrderCloth::getOrgId).collect(Collectors.toSet()))).stream()
                    .collect(Collectors.toMap(SysOrg::getId, SysOrg -> SysOrg));
        }
        for (OrderCloth record : orderCloths) {
            OrderClothVO orderClothVO = new OrderClothVO();
            BeanUtils.copyProperties(record, orderClothVO);
            if (record.getTakeClothAppUserId() != null && takeClothUserMap.containsKey(record.getTakeClothAppUserId())) {
                AppUserVO appUserVO = new AppUserVO();
                BeanUtils.copyProperties(takeClothUserMap.get(record.getTakeClothAppUserId()), appUserVO);
                orderClothVO.setTakeClothUserVO(appUserVO);
            }
            if (record.getSendClothAppUserId() != null && sendClothUserMap.containsKey(record.getSendClothAppUserId())) {
                AppUserVO appUserVO = new AppUserVO();
                BeanUtils.copyProperties(sendClothUserMap.get(record.getSendClothAppUserId()), appUserVO);
                orderClothVO.setSendClothUserVO(appUserVO);
            }
            if (SourceType.STORE.getCode().equals(orderClothVO.getSourceType())) {
                orderClothVO.setSysOrg(storeOrgMap.get(orderClothVO.getOrgId()));
            } else if (SourceType.FACTORY.getCode().equals(orderClothVO.getSourceType())) {
                orderClothVO.setSysOrg(factoryOrgMap.get(orderClothVO.getOrgId()));
            }
            orderClothVOS.add(orderClothVO);
        }
        return R.ok(orderClothVOS);
    }


    @ApiOperation("查询洗衣订单明细")
    @GetMapping(value = "getInfoById")
    public R<OrderClothVO> getInfoById(@RequestParam @ApiParam("订单ID") Long orderId) throws Exception {
        OrderCloth orderCloth = orderClothService.getOne(new QueryWrapper<OrderCloth>().lambda()
                .eq(OrderCloth::getId, orderId).eq(OrderCloth::getAppUserId, AuthHolder.userId()));
        if (orderCloth == null) {
            throw new ServiceException("未查询到订单信息");
        }

        OrderClothVO orderClothVO = new OrderClothVO();
        BeanUtils.copyProperties(orderCloth, orderClothVO);
        orderClothVO.setSysOrg(sysOrgService.getOne(new QueryWrapper<SysOrg>().lambda().eq(SysOrg::getId, orderCloth.getOrgId())
                .eq(SysOrg::getSourceType, orderCloth.getSourceType())));

        orderClothVO.setOrderClothItemVOS(
                orderClothItemService.buildWeAppOrderClothItemDetail(
                        orderClothItemService.list(new QueryWrapper<OrderClothItem>().lambda()
                                .eq(OrderClothItem::getOrderId, orderCloth.getId()))));

        if (TakeOrSendClothWay.DELIVERY.getCode().equals(orderCloth.getTakeClothWay())
                || TakeOrSendClothWay.DELIVERY.getCode().equals(orderCloth.getSendClothWay())) {
            Map<String, OrderDelivery> orderDeliveryMap = orderDeliveryService.list(
                            new QueryWrapper<OrderDelivery>().lambda()
                                    .eq(OrderDelivery::getOrderSn, orderCloth.getOrderNo()))
                    .stream().collect(Collectors.toMap(OrderDelivery::getClothOrderType
                            , OrderDelivery -> OrderDelivery));
            if (TakeOrSendClothWay.DELIVERY.getCode().equals(orderCloth.getTakeClothWay())) {
                orderClothVO.setCollectClothDeliverInfo(orderDeliveryMap.get(ClothOrderDeliveryType.collectCloth.getCode()));
            }
            if (TakeOrSendClothWay.DELIVERY.getCode().equals(orderCloth.getSendClothWay())) {
                orderClothVO.setTakeClothDeliverInfo(orderDeliveryMap.get(ClothOrderDeliveryType.takeCloth.getCode()));
            }
        }
        return R.ok(orderClothVO);
    }

    @Transactional(rollbackFor = Exception.class)
    @ApiOperation("洗衣订单配送订单下单")
    @PostMapping(value = "addSendClothDeliveryOrder")
    public R addSendClothDeliveryOrder(@RequestBody @Valid UpdateOrderClothTakeClothWayDTO updateOrderClothTakeClothWayDTO) throws Exception {
        return R.ok("配送订单单独支付已弃用");
    }


    @Transactional(rollbackFor = Exception.class)
    @ApiOperation("订单付款")
    @PostMapping(value = "clothOrderPay")
    public R<OrderPayResultVO> clothOrderPay(@Valid @RequestBody OrderClothAppPayDTO orderClothAppPayDTO) throws Exception {
        return R.ok(orderClothService.clothOrderAppPay(orderClothAppPayDTO));
    }

    @Transactional(rollbackFor = Exception.class)
    @ApiOperation("衣服确认送达")
    @GetMapping(value = "confirmSend")
    public R confirmSend(@RequestParam Long orderId) throws Exception {
        OrderCloth orderCloth = orderClothService.getOne(new QueryWrapper<OrderCloth>().lambda()
                .eq(OrderCloth::getId, orderId)
                .eq(OrderCloth::getAppUserId, AuthHolder.userId()));
        if (orderCloth == null) {
            throw new ServiceException("未查询到订单信息");
        }
        if (!ClothOrderStatusType.SENDING.getCode().equals(orderCloth.getOrderStatus())) {
            throw new ServiceException("当前订单状态为"
                    + EnumUtils.getEnumByType(orderCloth.getOrderStatus(), ClothOrderStatusType.class)
                    + "，无法进行确认送达操作");
        }
        orderCloth.setOrderStatus(ClothOrderStatusType.FINISH.getCode());
        orderClothService.updateById(orderCloth);
        orderClothItemService.update(new UpdateWrapper<OrderClothItem>().lambda()
                .set(OrderClothItem::getFlowStatus, ClothOrderFlowStatus.hasTake.getCode())
                .eq(OrderClothItem::getOrderId, orderId));
        List<OrderClothItem> orderClothItems = orderClothItemService.list(new QueryWrapper<OrderClothItem>()
                .lambda().eq(OrderClothItem::getOrderId, orderId));
        orderClothItemFlowRecordService.addRecordBatch(orderClothItems, ClothOrderFlowStatus.hasTake.getCode());
        return R.ok();
    }

    @ApiOperation("取消订单")
    @GetMapping(value = "cancel")
    public R cancel(@RequestParam @ApiParam("订单ID") Long orderId) throws Exception {
        OrderCloth orderCloth = orderClothService.getOne(new QueryWrapper<OrderCloth>().lambda()
                .eq(OrderCloth::getId, orderId).eq(OrderCloth::getAppUserId, AuthHolder.userId()));
        if (orderCloth == null) {
            throw new ServiceException("未查询到订单");
        }

        if (!(ClothOrderStatusType.APPOINTMENT.getCode().equals(orderCloth.getOrderStatus())
                || ClothOrderStatusType.WAITING_TO_DOOR.getCode().equals(orderCloth.getOrderStatus())
                || ClothOrderStatusType.HAS_TO_DOOR.getCode().equals(orderCloth.getOrderStatus())
                || ClothOrderStatusType.HAS_TAKING.getCode().equals(orderCloth.getOrderStatus())
                || ClothOrderStatusType.WAITING_FOR_PAY.getCode().equals(orderCloth.getOrderStatus()))) {
            throw new ServiceException("订单状态不正确，无法取消");
        }

        orderClothService.update(new UpdateWrapper<OrderCloth>().lambda()
                .set(OrderCloth::getOrderStatus, ClothOrderStatusType.CANCEL.getCode())
                .set(BaseEntity::getUpdateTime, DateUtils.getNowDate()).eq(OrderCloth::getId, orderId));

        orderClothItemService.update(new UpdateWrapper<OrderClothItem>().lambda()
                .set(OrderClothItem::getFlowStatus, ClothOrderFlowStatus.refund.getCode())
                .eq(OrderClothItem::getOrderId, orderId));
        List<OrderClothItem> orderClothItems = orderClothItemService.list(new QueryWrapper<OrderClothItem>()
                .lambda().eq(OrderClothItem::getOrderId, orderId));
        orderClothItemFlowRecordService.addRecordBatch(orderClothItems, ClothOrderFlowStatus.refund.getCode());
        return R.ok();
    }

    @ApiOperation("计算配送费金额")
    @GetMapping(value = "/calculateDeliveryPirce")
    public R<Map> calculateDeliveryPirce(Long orderId, String sendWay) throws Exception {
        Map<String, Object> maps = orderClothService.calculateDeliveryFee(orderId, sendWay);
        return R.ok(maps);
    }

}
