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.*;
import com.yiqi.common.exception.ServiceException;
import com.yiqi.common.utils.DateUtils;
import com.yiqi.common.utils.StringUtils;
import com.yiqi.order.domain.*;
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.OrderDeliveryVO;
import com.yiqi.order.domain.vo.weapp.WeAppOrderClothAppointmentVO;
import com.yiqi.order.service.IOrderClothItemService;
import com.yiqi.order.service.IOrderClothService;
import com.yiqi.order.service.IOrderClothStatusRecordService;
import com.yiqi.order.service.IOrderDeliveryService;
import com.yiqi.system.domain.SysOrg;
import com.yiqi.system.domain.SysStore;
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.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 IOrderDeliveryService orderDeliveryService;

    @Autowired
    private ISysOrgService sysOrgService;

    @Autowired
    private ISysStoreService sysStoreService;

    @Autowired
    private IOrderClothService orderClothService;

    @Autowired
    private IOrderClothItemService orderClothItemService;

    @Autowired
    private IOrderClothStatusRecordService orderClothStatusRecordService;

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

        LambdaQueryWrapper<OrderDelivery> queryWrapper = new LambdaQueryWrapper<OrderDelivery>();
        queryWrapper.eq(OrderDelivery::getDeliveryManId, AuthHolder.userId());
        if (appOrderClothDeliveryManQueryDTO.getDeliveryStatus() != null) {
            queryWrapper.eq(OrderDelivery::getDeliveryStatus, appOrderClothDeliveryManQueryDTO.getDeliveryStatus());
        }
        queryWrapper.orderByDesc(BaseEntity::getCreateTime);
        List<OrderDelivery> orderDeliveryList = orderDeliveryService.page(page
                , queryWrapper).getRecords();
        if (orderDeliveryList.size() == 0) {
            return R.ok(new ArrayList<>());
        }
        List<OrderDeliveryVO> orderDeliveryVOList = new ArrayList<>();
        for (OrderDelivery orderDelivery : orderDeliveryList) {
            OrderDeliveryVO orderDeliveryVO = new OrderDeliveryVO();
            BeanUtils.copyProperties(orderDelivery, orderDeliveryVO);
            //门店不为空
            if (orderDelivery.getStoreId() != null) {
                SysStore store = sysStoreService.getById(orderDelivery.getStoreId());
                orderDeliveryVO.setStoreName(store.getName());
                StoreAddressVO storeAddressVO = new StoreAddressVO();
                BeanUtils.copyProperties(store, storeAddressVO);
                orderDeliveryVO.setStoreAddress(storeAddressVO);
            }
            OrderCloth orderCloth = orderClothService.getOrderClothByOrderNo(orderDelivery.getOrderSn());
            OrderClothVO orderClothVO = new OrderClothVO();
            BeanUtils.copyProperties(orderCloth, orderClothVO);
            orderDeliveryVO.setOrderCloth(orderClothVO);
            orderDeliveryVOList.add(orderDeliveryVO);
        }
        return R.ok(orderDeliveryVOList);
    }


    @ApiOperation("配送员查询洗衣订单明细")
    @GetMapping(value = "delivery/getInfoById")
    public R<OrderClothVO> getInfoById(@RequestParam @ApiParam("订单ID") Long orderId) throws Exception {
        OrderCloth orderCloth = orderClothService.getOne(new QueryWrapper<OrderCloth>().lambda()
                .eq(OrderCloth::getId, orderId));
        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 = "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()));
        //更新配送订单
        OrderDelivery orderDelivery = orderDeliveryService.selectOrderDeliveryByOrderId(orderCloth.getOrderNo(), ClothOrderDeliveryType.collectCloth.getCode());
        orderDelivery.setDeliveryStatus(OrderDeliveryStatusEnum.HAS_TO_DOOR.getCode());
        orderDelivery.setFetchTime(DateUtils.getNowDate());
        orderDeliveryService.updateById(orderDelivery);
        orderClothStatusRecordService.addRecord(appOrderClothDeliveryChangeStatusDTO, orderCloth.getOrderNo()
                , ClothOrderStatusType.HAS_TO_DOOR.getCode(), AuthHolder.userId());
        return R.ok();
    }

    @Transactional(rollbackFor = Exception.class)
    @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()));

        //更新配送订单
        OrderDelivery orderDelivery = orderDeliveryService.selectOrderDeliveryByOrderId(orderCloth.getOrderNo(), ClothOrderDeliveryType.collectCloth.getCode());
        orderDelivery.setDeliveryStatus(OrderDeliveryStatusEnum.SEND_FINISH.getCode());
        orderDelivery.setFinishTime(DateUtils.getNowDate());
        orderDeliveryService.updateById(orderDelivery);

        orderClothStatusRecordService.addRecord(appOrderClothDeliveryChangeStatusDTO, orderCloth.getOrderNo()
                , ClothOrderStatusType.HAS_TAKING.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()));

        //更新配送订单
        OrderDelivery orderDelivery = orderDeliveryService.selectOrderDeliveryByOrderId(orderCloth.getOrderNo(), ClothOrderDeliveryType.takeCloth.getCode());
        orderDelivery.setDeliveryStatus(OrderDeliveryStatusEnum.SENDING.getCode());
        orderDelivery.setFetchTime(DateUtils.getNowDate());
        orderDeliveryService.updateById(orderDelivery);

        orderClothStatusRecordService.addRecord(appOrderClothDeliveryChangeStatusDTO, orderCloth.getOrderNo()
                , ClothOrderStatusType.SENDING.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()));

        //更新配送订单
        OrderDelivery orderDelivery = orderDeliveryService.selectOrderDeliveryByOrderId(orderCloth.getOrderNo(), ClothOrderDeliveryType.takeCloth.getCode());
        orderDelivery.setDeliveryStatus(OrderDeliveryStatusEnum.SEND_FINISH.getCode());
        orderDelivery.setFinishTime(DateUtils.getNowDate());
        orderDeliveryService.updateById(orderDelivery);

        orderClothStatusRecordService.addRecord(appOrderClothDeliveryChangeStatusDTO, orderCloth.getOrderNo()
                , ClothOrderStatusType.FINISH.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)));
    }
}
