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

import java.util.*;
import java.util.stream.Collectors;
import javax.annotation.Resource;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.http.HttpUtil;
import cn.iocoder.yudao.module.depository.dal.mysql.warehouse.WarehouseLineMapper;
import cn.iocoder.yudao.module.depository.dto.LogisticsInfoDto;
import cn.iocoder.yudao.module.order.dal.dataobject.order.OrderDO;
import cn.iocoder.yudao.module.order.dto.OrderTimeResultListDto;
import cn.iocoder.yudao.module.order.enums.OrderAirTimeEnum;
import cn.iocoder.yudao.module.order.enums.OrderSeaTimeEnum;
import cn.iocoder.yudao.module.order.enums.OrderStatusEnum;
import cn.iocoder.yudao.module.order.service.order.OrderService;
import cn.iocoder.yudao.module.order.service.order.OrderTimeService;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import cn.iocoder.yudao.framework.mybatis.core.vo.PageVO;
import cn.iocoder.yudao.framework.mybatis.core.service.AbstractService;
import cn.iocoder.yudao.module.order.vo.orderTime.*;
import cn.iocoder.yudao.module.order.dal.dataobject.orderTime.OrderTimeDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.order.convert.orderTime.OrderTimeConvert;
import cn.iocoder.yudao.module.order.dal.mysql.orderTime.OrderTimeMapper;


/**
 * 下单时间轴事件 Service 实现类
 *
 * @author 系统管理员
 */
@Service
@Slf4j
@Validated
public class OrderTimeServiceImpl extends AbstractService<OrderTimeMapper, OrderTimeDO> implements OrderTimeService {

    @Resource
    private OrderTimeMapper orderTimeMapper;
    @Resource
    private OrderService orderService;
    @Resource
    private WarehouseLineMapper warehouseLineMapper;
    private static final String OLD_API_URL = "http://pda.groupage.cn/apipc/common/order_log?number=%s";

    @Override
    public Long createOrderTime(OrderTimeCreateReqVO createReqVO) {
        // 插入
        OrderTimeDO orderTime = OrderTimeConvert.INSTANCE.convert(createReqVO);
        orderTimeMapper.insert(orderTime);
        // 返回
        return orderTime.getId();
    }

    public Date getCustomerOperateDate(long customerId,long newcustomerservice)
    {
        return orderTimeMapper.getCustomerOperateDate(customerId,
                newcustomerservice);
    }

    @Override
    public void updateOrderTime(OrderTimeUpdateReqVO updateReqVO) {
        // 校验存在
//        this.validateOrderTimeExists(updateReqVO.getId());
        // 更新
        OrderTimeDO updateObj = OrderTimeConvert.INSTANCE.convert(updateReqVO);
        orderTimeMapper.updateById(updateObj);
    }


    @Override
    public void updateOrderEstBookSeaTime(String containerNumber, Integer transportId, Date estTime) {
        if (transportId == 1) {
            List<OrderDO> orderDOList = orderService.list(new LambdaQueryWrapper<OrderDO>().eq(OrderDO::getContainerNumber, containerNumber));
            for (OrderDO orderDO : orderDOList) {
                String remarksZh = String.format(OrderSeaTimeEnum.SEA_INSTALLED_CABINET.getRemarksZh(), Objects.nonNull(estTime) ? DateUtil.formatDateTime(estTime) : "");
                String remarksEn = String.format(OrderSeaTimeEnum.SEA_INSTALLED_CABINET.getRemarksEn(), Objects.nonNull(estTime) ? DateUtil.formatDateTime(estTime) : "");
                this.update(new LambdaUpdateWrapper<OrderTimeDO>().set(OrderTimeDO::getRemarksZh, remarksZh).set(OrderTimeDO::getRemarksEn, remarksEn)
                        .eq(OrderTimeDO::getOrderId, orderDO.getOrderId())
                        .eq(OrderTimeDO::getType, 0)
                        .eq(OrderTimeDO::getStatus, OrderSeaTimeEnum.SEA_INSTALLED_CABINET.getValue()));
            }
        }
    }


    @Override
    public void updateOrderEstShippingTime(String containerNumber, Integer transportId, Date estTime) {
        List<OrderDO> orderDOList = orderService.list(new LambdaQueryWrapper<OrderDO>().eq(OrderDO::getContainerNumber, containerNumber));
        if (transportId == 1) {
            for (OrderDO orderDO : orderDOList) {
                String remarksZh = String.format(OrderSeaTimeEnum.SEA_HAS_TAKEN_OFF.getRemarksZh(), Objects.nonNull(estTime) ? DateUtil.formatDateTime(estTime) : "");
                String remarksEn = String.format(OrderSeaTimeEnum.SEA_HAS_TAKEN_OFF.getRemarksEn(), Objects.nonNull(estTime) ? DateUtil.formatDateTime(estTime) : "");
                this.update(new LambdaUpdateWrapper<OrderTimeDO>().set(OrderTimeDO::getRemarksZh, remarksZh).set(OrderTimeDO::getRemarksEn, remarksEn)
                        .eq(OrderTimeDO::getOrderId, orderDO.getOrderId())
                        .eq(OrderTimeDO::getType, 0)
                        .eq(OrderTimeDO::getStatus, OrderSeaTimeEnum.SEA_HAS_TAKEN_OFF.getValue()));
            }
        }
        if (transportId == 3) {
            for (OrderDO orderDO : orderDOList) {
                LogisticsInfoDto logisticsCountryInfoDto1 = warehouseLineMapper.getStartInfoAndDestInfoByLineId(orderDO.getLineId());
                if (Objects.nonNull(logisticsCountryInfoDto1)) {
                    String remarksZh = String.format(OrderAirTimeEnum.AIR_HAS_TAKEN_OFF.getRemarksZh(), Objects.nonNull(estTime) ? DateUtil.formatDateTime(estTime) : "", logisticsCountryInfoDto1.getDestCountryTitleZh());
                    String remarksEn = String.format(OrderAirTimeEnum.AIR_HAS_TAKEN_OFF.getRemarksEn(), logisticsCountryInfoDto1.getDestCountryTitleEn(), Objects.nonNull(estTime) ? DateUtil.formatDateTime(estTime) : "");
                    this.update(new LambdaUpdateWrapper<OrderTimeDO>().set(OrderTimeDO::getRemarksZh, remarksZh).set(OrderTimeDO::getRemarksEn, remarksEn)
                            .eq(OrderTimeDO::getOrderId, orderDO.getOrderId())
                            .eq(OrderTimeDO::getType, 0)
                            .eq(OrderTimeDO::getStatus, OrderAirTimeEnum.AIR_HAS_TAKEN_OFF.getValue()));
                }
            }
        }
    }

    @Override
    public void deleteOrderTime(Long id) {
        // 校验存在
//        this.validateOrderTimeExists(id);
        // 删除
        orderTimeMapper.deleteById(id);
    }

//    private void validateOrderTimeExists(Long id) {
//        if (orderTimeMapper.selectById(id) == null) {
//            throw exception(ORDER_TIME_NOT_EXISTS);
//        }
//    }


    @Override
    public void preReverseReviewDeleteOrderTime(String containerNumber) {
        // 获取自编号下订单指定类型的最新动态
        List<OrderTimeDO> orderTimeDOList = orderTimeMapper.newOrderTimeByContainerNumberAndStatus(containerNumber, OrderSeaTimeEnum.SEA_IN_WAREHOUSE.getValue());
        for (OrderTimeDO orderTimeDO : orderTimeDOList) {
            // 删除当前动态后面添加的所有动态数据
            this.remove(new LambdaQueryWrapper<OrderTimeDO>()
                    .gt(OrderTimeDO::getId, orderTimeDO.getId())
                    .eq(OrderTimeDO::getOrderId, orderTimeDO.getOrderId()));
        }
    }

    @Override
    public void preReverseReviewDeleteOrderTime(Long orderId) {
        // 获取自编号下订单指定类型的最新动态
        List<OrderTimeDO> orderTimeDOList = orderTimeMapper.newOrderTimeByOrderIdAndStatus(orderId, OrderSeaTimeEnum.SEA_IN_WAREHOUSE.getValue());
        for (OrderTimeDO orderTimeDO : orderTimeDOList) {
            // 删除当前动态后面添加的所有动态数据
            this.remove(new LambdaQueryWrapper<OrderTimeDO>()
                    .gt(OrderTimeDO::getId, orderTimeDO.getId())
                    .eq(OrderTimeDO::getOrderId, orderTimeDO.getOrderId()));
        }
    }

    @Override
    public void sortingReverseReviewDeleteOrderTime(String containerNumber) {
        // 获取自编号下订单指定类型的最新动态
        List<OrderTimeDO> orderTimeDOList = orderTimeMapper.newOrderTimeByContainerNumberAndStatus(containerNumber, OrderAirTimeEnum.AIR_PACKED.getValue());
        for (OrderTimeDO orderTimeDO : orderTimeDOList) {
            this.remove(new LambdaQueryWrapper<OrderTimeDO>()
                    .gt(OrderTimeDO::getId, orderTimeDO.getId())
                    .eq(OrderTimeDO::getOrderId, orderTimeDO.getOrderId()));
        }
    }

    @Override
    public void sortingReverseReviewDeleteOrderTime(Long orderId) {
        // 获取自编号下订单指定类型的最新动态
        List<OrderTimeDO> orderTimeDOList = orderTimeMapper.newOrderTimeByOrderIdAndStatus(orderId, OrderAirTimeEnum.AIR_PACKED.getValue());
        for (OrderTimeDO orderTimeDO : orderTimeDOList) {
            // 删除当前动态后面添加的所有动态数据
            this.remove(new LambdaQueryWrapper<OrderTimeDO>()
                    .gt(OrderTimeDO::getId, orderTimeDO.getId())
                    .eq(OrderTimeDO::getOrderId, orderTimeDO.getOrderId()));
        }
    }

    @Override
    public OrderTimeDO getOrderTime(Long id) {
        return orderTimeMapper.selectById(id);
    }

    @Override
    public List<OrderTimeDO> getOrderTimeList(Collection<Long> ids) {
        return orderTimeMapper.selectBatchIds(ids);
    }

    @Override
    public List<OrderTimeDO> getOrderTimeList(Long orderId) {
        return orderTimeMapper.selectList(new LambdaQueryWrapper<OrderTimeDO>().eq(OrderTimeDO::getOrderId, orderId));
    }

    @Override
    public PageResult<OrderTimeDO> getOrderTimePage(OrderTimeQueryVO query, PageVO page) {
        return orderTimeMapper.selectPage(page, query);
    }

    @Override
    public List<OrderTimeDO> getOrderTimeList(OrderTimeQueryVO query) {
        return orderTimeMapper.selectList(query);
    }


    @Override
    @Cacheable(cacheNames = "jd:order:time", key = "#orderId +':'+ #orderNo")
    public List<OrderTimeBackVO> orderTimeList(Long orderId, String orderNo) {
        if (Objects.isNull(orderId)) {
            // 先使用订单编号或者提单编号查询，任意一个匹配上获取第一条数据
            OrderDO orderDO = orderService.getOne(new LambdaQueryWrapper<OrderDO>()
                    .and(e -> e.eq(OrderDO::getOrderNo, orderNo)
                            .or()
                            .eq(OrderDO::getTidanNo, orderNo))
                    .orderByDesc(OrderDO::getOrderId)
                    .last("limit 1"));
//            if (Objects.isNull(orderDO)){
//                // 如果订单编号查询为空，则再使用提单编号查询
//                orderDO = orderService.getOne(new LambdaQueryWrapper<OrderDO>()
//                        .eq(OrderDO::getTidanNo, orderNo)
//                        .last("limit 1"));
//            }
            if (Objects.isNull(orderDO)) {
                // 当新系统查询订单信息都为空，则调用旧系统api查询
                String result = HttpUtil.get(String.format(OLD_API_URL, orderNo));
                log.info("请求结果：{}", result);
                if (StringUtils.isBlank(result)) {
                    return new ArrayList<>();
                }
                try {
                    OrderTimeResultListDto resultListDto = JSONObject.parseObject(result, OrderTimeResultListDto.class);
                    return Objects.nonNull(resultListDto) && 0 == resultListDto.getCode() ? resultListDto.getData() : Collections.emptyList();
                } catch (Exception e) {
                    return new ArrayList<>();
                }
            }
            orderId = orderDO.getOrderId();
        }
        List<OrderTimeDO> list = this.getOrderTimeList(orderId);
        if (CollectionUtil.isEmpty(list)) {
            return new ArrayList<>();
        }
        // app-web状态类型去重返回
        List<OrderTimeDO> backList = new ArrayList<>();
        Map<String, List<OrderTimeDO>> timeListMap = list.stream().collect(Collectors.groupingBy(OrderTimeDO::getStatusType));
        for (Map.Entry<String, List<OrderTimeDO>> entry : timeListMap.entrySet()) {
            List<OrderTimeDO> enList = entry.getValue().stream().sorted(Comparator.comparing(OrderTimeDO::getId)).collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(enList)) {
                backList.add(enList.get(0));
            }
        }
        backList = backList.stream().filter(t -> t.getStatus() != 15 && t.getStatus() != 150330).sorted(Comparator.comparing(OrderTimeDO::getId).reversed()).collect(Collectors.toList());
        return OrderTimeConvert.INSTANCE.convertList(backList);
    }
}
