package com.yiqi.api.controller.order;

import cn.hutool.db.sql.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.baomidou.mybatisplus.extension.plugins.pagination.Page;
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.PageVO;
import com.yiqi.common.core.domain.R;
import com.yiqi.common.enums.ClothOrderDeliveryType;
import com.yiqi.common.enums.ClothOrderStatusType;
import com.yiqi.common.enums.OrderRefundStatus;
import com.yiqi.common.enums.SourceType;
import com.yiqi.common.exception.ServiceException;
import com.yiqi.common.utils.StringUtils;
import com.yiqi.order.domain.OrderCloth;
import com.yiqi.order.domain.OrderClothDeliveryAddress;
import com.yiqi.order.domain.OrderClothStatusRecord;
import com.yiqi.order.domain.dto.weapp.AppOrderClothDeliveryChangeStatusDTO;
import com.yiqi.order.domain.dto.weapp.AppOrderClothDeliveryManQueryDTO;
import com.yiqi.order.domain.vo.OrderClothVO;
import com.yiqi.order.domain.vo.weapp.WeAppOrderClothAppointmentVO;
import com.yiqi.order.service.IOrderClothDeliveryAddressService;
import com.yiqi.order.service.IOrderClothService;
import com.yiqi.order.service.IOrderClothStatusRecordService;
import com.yiqi.system.domain.SysOrg;
import com.yiqi.system.service.ISysOrgService;
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.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

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

/**
 * @author xiaohei
 * @date 2024/1/22
 */
@Api(tags = "配送员相关订单接口")
@RestController
@RequestMapping(value = UrlConstants.wxappApi + "/order")
public class WeAppOrderClothDeliveryManController {

    @Autowired
    private IOrderClothDeliveryAddressService orderClothDeliveryAddressService;

    @Autowired
    private ISysOrgService sysOrgService;

    @Autowired
    private IOrderClothService orderClothService;

    @Autowired
    private IOrderClothStatusRecordService orderClothStatusRecordService;

    @ApiOperation("配送员查询订单列表")
    @PostMapping(value = "findDeliveryPage")
    public R<List<OrderClothVO>> findDeliveryManPage(@RequestBody @Valid AppOrderClothDeliveryManQueryDTO appOrderClothDeliveryManQueryDTO) throws Exception{
        Page<OrderCloth> page = new Page<>(appOrderClothDeliveryManQueryDTO.getPageNum()
                ,appOrderClothDeliveryManQueryDTO.getPageSize());
        page.setSearchCount(false);

        LambdaQueryWrapper<OrderCloth> queryWrapper = new QueryWrapper<OrderCloth>().lambda()
                .eq(OrderCloth::getRefundStatus,OrderRefundStatus.OK.getCode())
                .and(orderClothLambdaQueryWrapper -> orderClothLambdaQueryWrapper
                        .eq(OrderCloth::getSendClothAppUserId,AuthHolder.userId())
                        .or()
                        .eq(OrderCloth::getTakeClothAppUserId,AuthHolder.userId())
                )
//                .and(orderClothLambdaQueryWrapper -> orderClothLambdaQueryWrapper
//                        .eq(OrderCloth::getOrderStatus,ClothOrderStatusType.WAITING_TO_DOOR.getCode())
//                        .or()
//                        .eq(OrderCloth::getOrderStatus,ClothOrderStatusType.HAS_TO_DOOR.getCode())
//                        .or()
//                        .eq(OrderCloth::getOrderStatus,ClothOrderStatusType.WAITING_TO_SEND.getCode())
//                        .or()
//                        .eq(OrderCloth::getOrderStatus,ClothOrderStatusType.SENDING.getCode())
//                        .or()
//                        .eq(OrderCloth::getOrderStatus,ClothOrderStatusType.FINISH.getCode()))
                ;
        if(StringUtils.isNotEmpty(appOrderClothDeliveryManQueryDTO.getOrderStatus())){
            queryWrapper.eq(OrderCloth::getOrderStatus,appOrderClothDeliveryManQueryDTO.getOrderStatus());
        }
        queryWrapper.orderByDesc(BaseEntity::getCreateTime);
        List<OrderCloth> orderCloths = orderClothService.page(page
                ,queryWrapper).getRecords();
        if(orderCloths.size() == 0){
            return R.ok(new ArrayList<>());
        }

        List<OrderClothDeliveryAddress> list = orderClothDeliveryAddressService.list(new QueryWrapper<OrderClothDeliveryAddress>().lambda()
                .in(OrderClothDeliveryAddress::getOrderId
                        ,orderCloths.stream().map(OrderCloth::getId).collect(Collectors.toSet())));
        Map<Long,OrderClothDeliveryAddress> collectAddressMap = list.stream().filter(orderClothDeliveryAddress -> ClothOrderDeliveryType.collectCloth.getCode()
                .equals(orderClothDeliveryAddress.getClothOrderType()))
                .collect(Collectors.toMap(OrderClothDeliveryAddress::getOrderId,OrderClothDeliveryAddress -> OrderClothDeliveryAddress));
        Map<Long,OrderClothDeliveryAddress> takeAddressMap = list.stream().filter(orderClothDeliveryAddress -> ClothOrderDeliveryType.takeCloth.getCode()
                .equals(orderClothDeliveryAddress.getClothOrderType()))
                .collect(Collectors.toMap(OrderClothDeliveryAddress::getOrderId,OrderClothDeliveryAddress -> OrderClothDeliveryAddress));
        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())))
                    .eq(SysOrg::getSourceType,SourceType.FACTORY.getCode())).stream().collect(Collectors.toMap(SysOrg::getId,SysOrg -> SysOrg));
        }
        List<OrderClothVO> orderClothVOS = new ArrayList<>();
        for (OrderCloth orderCloth : orderCloths) {
            OrderClothVO orderClothVO = new OrderClothVO();
            BeanUtils.copyProperties(orderCloth,orderClothVO);
            orderClothVO.setCollectClothDeliverInfo(collectAddressMap.get(orderCloth.getId()));
            orderClothVO.setTakeClothDeliverInfo(takeAddressMap.get(orderCloth.getId()));
            if(SourceType.FACTORY.getCode().equals(orderCloth.getSourceType())){
                orderClothVO.setSysOrg(factoryOrgMap.get(orderCloth.getOrgId()));
            }else if(SourceType.STORE.getCode().equals(orderCloth.getSourceType())){
                orderClothVO.setSysOrg(storeOrgMap.get(orderCloth.getOrgId()));
            }else{
                orderClothVO.setSysOrg(SysOrg.buildManagerOrg());
            }
            orderClothVOS.add(orderClothVO);
        }
        return R.ok(orderClothVOS);
    }

    @Transactional(rollbackFor = Exception.class)
    @ApiOperation("上门取衣")
    @PostMapping(value = "toDoor")
    public R toDoor(@RequestBody @Valid AppOrderClothDeliveryChangeStatusDTO appOrderClothDeliveryChangeStatusDTO) throws Exception{
        OrderCloth orderCloth = orderClothService.getOne(new QueryWrapper<OrderCloth>().lambda()
                .eq(OrderCloth::getId,appOrderClothDeliveryChangeStatusDTO.getOrderId()).eq(OrderCloth::getTakeClothAppUserId, AuthHolder.userId())
                .eq(OrderCloth::getRefundStatus, OrderRefundStatus.OK.getCode()));
        if(orderCloth == null){
            throw new ServiceException("未查询到订单");
        }

        if(!ClothOrderStatusType.WAITING_TO_DOOR.getCode().equals(orderCloth.getOrderStatus())){
            throw new ServiceException("订单状态不是待上门状态，无法进行上门取衣操作");
        }

        orderClothService.update(new UpdateWrapper<OrderCloth>().lambda()
                .set(OrderCloth::getOrderStatus,ClothOrderStatusType.HAS_TO_DOOR.getCode())
                .eq(OrderCloth::getId,appOrderClothDeliveryChangeStatusDTO.getOrderId()));

        orderClothStatusRecordService.addRecord(appOrderClothDeliveryChangeStatusDTO,orderCloth.getOrderNo()
                ,ClothOrderStatusType.HAS_TO_DOOR.getCode(), AuthHolder.userId());
        return R.ok();
    }

    @ApiOperation("送回到店")
    @PostMapping(value = "take")
    public R take(@RequestBody @Valid AppOrderClothDeliveryChangeStatusDTO appOrderClothDeliveryChangeStatusDTO) throws Exception{
        OrderCloth orderCloth = orderClothService.getOne(new QueryWrapper<OrderCloth>().lambda()
                .eq(OrderCloth::getId,appOrderClothDeliveryChangeStatusDTO.getOrderId()).eq(OrderCloth::getTakeClothAppUserId, AuthHolder.userId())
                .eq(OrderCloth::getRefundStatus, OrderRefundStatus.OK.getCode()));
        if(orderCloth == null){
            throw new ServiceException("未查询到订单");
        }

        if(!ClothOrderStatusType.HAS_TO_DOOR.getCode().equals(orderCloth.getOrderStatus())){
            throw new ServiceException("订单状态不是已上门状态，无法进行送回到店确认操作");
        }

        orderClothService.update(new UpdateWrapper<OrderCloth>().lambda()
                .set(OrderCloth::getOrderStatus,ClothOrderStatusType.HAS_TAKING.getCode())
                .eq(OrderCloth::getId,appOrderClothDeliveryChangeStatusDTO.getOrderId()));

        orderClothStatusRecordService.addRecord(appOrderClothDeliveryChangeStatusDTO,orderCloth.getOrderNo()
                ,ClothOrderStatusType.HAS_TO_DOOR.getCode(), AuthHolder.userId());
        return R.ok();
    }

    @ApiOperation("开始送衣")
    @PostMapping(value = "send")
    public R send(@RequestBody @Valid AppOrderClothDeliveryChangeStatusDTO appOrderClothDeliveryChangeStatusDTO) throws Exception{
        OrderCloth orderCloth = orderClothService.getOne(new QueryWrapper<OrderCloth>().lambda()
                .eq(OrderCloth::getId,appOrderClothDeliveryChangeStatusDTO.getOrderId()).eq(OrderCloth::getSendClothAppUserId, AuthHolder.userId())
                .eq(OrderCloth::getRefundStatus, OrderRefundStatus.OK.getCode()));
        if(orderCloth == null){
            throw new ServiceException("未查询到订单");
        }

        if(!ClothOrderStatusType.WAITING_TO_SEND.getCode().equals(orderCloth.getOrderStatus())){
            throw new ServiceException("订单状态不是待送衣状态，无法进行送衣操作");
        }

        orderClothService.update(new UpdateWrapper<OrderCloth>().lambda()
                .set(OrderCloth::getOrderStatus,ClothOrderStatusType.SENDING.getCode())
                .eq(OrderCloth::getId,appOrderClothDeliveryChangeStatusDTO.getOrderId()));

        orderClothStatusRecordService.addRecord(appOrderClothDeliveryChangeStatusDTO,orderCloth.getOrderNo()
                ,ClothOrderStatusType.HAS_TO_DOOR.getCode(), AuthHolder.userId());
        return R.ok();
    }

    @ApiOperation("配送完成")
    @PostMapping(value = "finish")
    public R finish(@RequestBody @Valid AppOrderClothDeliveryChangeStatusDTO appOrderClothDeliveryChangeStatusDTO) throws Exception{
        OrderCloth orderCloth = orderClothService.getOne(new QueryWrapper<OrderCloth>().lambda()
                .eq(OrderCloth::getId,appOrderClothDeliveryChangeStatusDTO.getOrderId()).eq(OrderCloth::getSendClothAppUserId, AuthHolder.userId())
                .eq(OrderCloth::getRefundStatus, OrderRefundStatus.OK.getCode()));
        if(orderCloth == null){
            throw new ServiceException("未查询到订单");
        }

        if(!ClothOrderStatusType.SENDING.getCode().equals(orderCloth.getOrderStatus())){
            throw new ServiceException("订单状态不是送衣中状态，无法进行完成操作");
        }

        orderClothService.update(new UpdateWrapper<OrderCloth>().lambda()
                .set(OrderCloth::getOrderStatus,ClothOrderStatusType.FINISH.getCode())
                .eq(OrderCloth::getId,appOrderClothDeliveryChangeStatusDTO.getOrderId()));

        orderClothStatusRecordService.addRecord(appOrderClothDeliveryChangeStatusDTO,orderCloth.getOrderNo()
                ,ClothOrderStatusType.HAS_TO_DOOR.getCode(), AuthHolder.userId());
        return R.ok();
    }

    @ApiOperation("查询订单状态变更记录")
    @GetMapping(value = "getStatusRecordList")
    public R<List<OrderClothStatusRecord>> getStatusRecordList(@RequestParam @ApiParam("订单ID") Long orderId) throws Exception{
        return R.ok(orderClothStatusRecordService.list(new QueryWrapper<OrderClothStatusRecord>().lambda().eq(OrderClothStatusRecord::getOrderId,orderId)));
    }
}
