package com.sckw.fleet.service;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.sckw.core.exception.SystemException;
import com.sckw.core.model.base.BaseModel;
import com.sckw.core.model.constant.Global;
import com.sckw.core.utils.BeanUtils;
import com.sckw.core.utils.CollectionUtils;
import com.sckw.core.utils.DateUtils;
import com.sckw.core.utils.StringUtils;
import com.sckw.core.web.constant.HttpStatus;
import com.sckw.core.web.context.LoginUserHolder;
import com.sckw.core.web.response.HttpResult;
import com.sckw.core.web.response.result.PageDataResult;
import com.sckw.fleet.dao.KwfFleetMapper;
import com.sckw.fleet.model.KwfFleet;
import com.sckw.fleet.model.KwfFleetTruck;
import com.sckw.fleet.model.KwfTruck;
import com.sckw.fleet.model.TmsTruckAxleNum;
import com.sckw.fleet.model.dto.KwfFleetDto;
import com.sckw.fleet.model.enums.TruckTypeEnum;
import com.sckw.fleet.model.request.QueryFleetReq;
import com.sckw.fleet.model.vo.KwfFleetTruckCountVo;
import com.sckw.fleet.model.vo.KwfFleetVo;
import com.sckw.fleet.model.vo.QueryFleetResp;
import com.sckw.fleet.repository.KwfFleetRepository;
import com.sckw.fleet.repository.KwfFleetTruckRepository;
import com.sckw.fleet.repository.KwfTruckAxleNumRepository;
import com.sckw.fleet.repository.KwfTruckRepository;
import com.sckw.system.api.RemoteSystemService;
import com.sckw.system.api.model.dto.res.EntCacheResDto;
import com.sckw.system.api.model.dto.res.UserCacheResDto;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author zk
 * @desc 车队
 * @date 2023/7/6 0006
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class KwfFleetService {

    @Autowired
    KwfFleetMapper fleetDao;
    @DubboReference(version = "1.0.0", group = "design", check = false)
    private RemoteSystemService remoteSystemService;
    private final KwfFleetRepository kwfFleetRepository;
    private final KwfFleetTruckRepository kwfFleetTruckRepository;
    private final KwfTruckAxleNumRepository kwfTruckAxleNumRepository;
    @Autowired
    private KwfTruckRepository kwfTruckRepository;

    /**
     * @param key 主键id
     * @desc 根据主键查询
     * @author zk
     * @date 2023/7/6
     **/
    public KwfFleet selectByKey(Long key) {
        return fleetDao.selectById(key);
    }

    /**
     * @param params 分页参数
     * @desc 分页查询
     * @author zk
     * @date 2023/7/6
     **/
    public List<KwfFleetVo> findPage(Map<String, Object> params) {
        /**获取查询数据集**/
        params.put("entId", LoginUserHolder.getEntId());
        List<KwfFleetVo> fleets = fleetDao.findPage(params);

        /**获取查询数据**/
        List<Long> createBys = new ArrayList<>();
        for (KwfFleetVo fleetVo:fleets) {
            createBys.add(Long.parseLong(fleetVo.getCreateBy()));
        }
        //用户数据集
        createBys = createBys.stream().distinct().collect(Collectors.toList());
        Map<Long, UserCacheResDto> users = remoteSystemService.queryUserCacheMapByIds(createBys);

        /**数据组装**/
        for (KwfFleetVo fleetVo:fleets) {
            UserCacheResDto user = users == null ? null : users.get(Long.parseLong(fleetVo.getCreateBy()));
            fleetVo.setCreateByName(user != null ? user.getName() : null);
        }
        return fleets;
    }

    /**
     * @param params 查询参数
     * @desc 查询
     * @author zk
     * @date 2023/7/6
     **/
    public List<Map<String, Object>> findList(Map<String, Object> params) {
        return fleetDao.findList(params);
    }

    /**
     * @param params 新增参数
     * @desc 新增司机
     * @author zk
     * @date 2023/7/6
     **/
    public HttpResult add(KwfFleetDto params) {
        /**唯一性交易**/
        List<Map<String, Object>> fleets = fleetDao.findList(new HashMap<>(Global.NUMERICAL_SIXTEEN){{
            put("wholeName", params.getName()); put("entId", LoginUserHolder.getEntId());}});
        if (!CollectionUtils.isEmpty(fleets)) {
            return HttpResult.error("车队班组已存在！");
        }

        /**新增**/
        KwfFleet fleet = new KwfFleet();
        BeanUtils.copyProperties(params, fleet);
        fleet.setEntId(LoginUserHolder.getEntId());
        int count = fleetDao.insert(fleet);
        return count > 0 ? HttpResult.ok("车队信息新增成功！") : HttpResult.error("车队信息新增失败！");
    }

    /**
     * @param params 修改参数
     * @desc 修改司机
     * @author zk
     * @date 2023/7/6
     **/
    public HttpResult update(KwfFleetDto params) {
        /**唯一性交易**/
        List<Map<String, Object>> fleets = fleetDao.findList(new HashMap<>(Global.NUMERICAL_SIXTEEN){{
            put("name", params.getName()); put("entId", LoginUserHolder.getEntId());}});
        //校验list中对象key值是否存在与value不一致的情况
        boolean bool = CollectionUtils.listByKeyValueV1(fleets, "id", params.getId());
        if (bool) {
            return HttpResult.error("车队班组已存在！");
        }

        /**更新**/
        KwfFleet fleet = new KwfFleet();
        BeanUtils.copyProperties(params, fleet);
        int count = fleetDao.updateById(fleet);
        return count > 0 ? HttpResult.ok("车队信息修改成功！") : HttpResult.error("车队信息修改失败！");
    }

    /**
     * @param {ids：主键ID（多个以逗号隔开）}
     * @description 删除
     * @author zk
     * @date 2023/7/6
     **/
    public HttpResult del(String ids) {
        /*1.数据校验*/
        if (StringUtils.isBlank(ids)) {
            return HttpResult.error("请选择要删除的数据！");
        }

        String[] idArray = ids.split(",");
        for (String id : idArray) {
            KwfFleet fleet = fleetDao.selectById(id);
            if (fleet != null) {
                fleet.setDelFlag(Global.YES);
                if (fleetDao.updateById(fleet) <= 0) {
                    throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.DELETE_FAIL);
                }
            } else {
                return HttpResult.error("选择删除的数据已不存在！");
            }
        }
        return HttpResult.ok("删除成功！");
    }

    /**
     * @param params {entId 企业ID, fleetName 车队班组名称}
     * @desc 车辆实况统计
     * @author zk
     * @date 2023/8/4
     **/
    public Map<String, Object> findTruckList(Map<String, Object> params) {
        //全量数据统计
        params.put("entId", LoginUserHolder.getEntId());
        List<KwfFleetTruckCountVo> truckCounts = fleetDao.findTruckList(new HashMap<>(Global.NUMERICAL_SIXTEEN){{put("entId", LoginUserHolder.getEntId());}});
        KwfFleetTruckCountVo truck = new KwfFleetTruckCountVo();
        truck.setFleetTotal(truckCounts != null ? truckCounts.size() : Global.NUMERICAL_ZERO);
        for (KwfFleetTruckCountVo truckCount:truckCounts) {
            truck.setIdleTotal(truckCount.getIdleTotal() != null ? truckCount.getIdleTotal() + truck.getIdleTotal() : truck.getIdleTotal());
            truck.setTruckTotal(truckCount.getTruckTotal() != null ? truckCount.getTruckTotal() + truck.getTruckTotal() : truck.getTruckTotal());
            truck.setBusyTotal(truckCount.getBusyTotal() != null ? truckCount.getBusyTotal() + truck.getBusyTotal() : truck.getBusyTotal());
        }

        //筛选数据统计
        truckCounts = fleetDao.findTruckList(params);

        //返回数据
        Map<String, Object> result = new HashMap<>(Global.NUMERICAL_SIXTEEN);
        result.put("truckCount", truck);
        result.put("truckCounts", truckCounts);
        return result;
    }

    public PageDataResult<QueryFleetResp> findFleetByPage(QueryFleetReq req) {
        log.info("查询车队列表请求：{}", JSON.toJSONString( req));
        Set<Long> allEnt = getAllEnt(req);
        Long fleetId = org.apache.commons.lang3.StringUtils.isNotBlank(req.getFleetId()) ?
                Long.valueOf(req.getFleetId()) : null;
        IPage<KwfFleet> page = kwfFleetRepository.queryByPage(allEnt,fleetId,req.getPageNum(),
                req.getPageSize());
        List<KwfFleet> records = page.getRecords();
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(records)){
            return PageDataResult.empty(req.getPageNum(), req.getPageSize());
        }
        Set<Long> userIds = Sets.newHashSet();
        Set<Long> fleetIds = Sets.newHashSet();
        Set<Object> objects = Sets.newHashSet();
        records.forEach(item -> {
            userIds.add(item.getCreateBy());
            userIds.add(item.getCaptainId());
            fleetIds.add(item.getId());
        });
        //查询用户信息
        Map<Long, UserCacheResDto> userIdAndUserCacheResDtoMap =
                remoteSystemService.queryUserCacheMapByIds(new ArrayList<>(userIds));
        //查询车辆
        List<KwfFleetTruck> kwfFleetTrucks = kwfFleetTruckRepository.queryByFleetIds(fleetIds);
        Map<Long, List<KwfFleetTruck>> fleetIdAndKwfFleetTruckList = Maps.newHashMap();
        Set<Long> truckIds = Sets.newHashSet();
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(kwfFleetTrucks)){
            fleetIdAndKwfFleetTruckList =
                    kwfFleetTrucks.stream().collect(Collectors.groupingBy(KwfFleetTruck::getFleetId));
            truckIds = kwfFleetTrucks.stream().map(KwfFleetTruck::getTruckId).collect(Collectors.toSet());
        }
        //查询车辆信息
        Map<Long, KwfTruck> truckIdAndTruckMap = Maps.newHashMap();
        Set<Integer> carAxis = Sets.newHashSet();
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(truckIds)){
            List<KwfTruck> trucks = kwfTruckRepository.queryByTruckIds(truckIds);
            if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(trucks)){
                truckIdAndTruckMap = trucks.stream()
                        .collect(Collectors.toMap(BaseModel::getId,
                        Function.identity(), (e1, e2) -> e1));
                carAxis = trucks.stream()
                        .filter(x-> org.apache.commons.lang3.StringUtils.isNotBlank(x.getCarAxis()))
                        .map(x->Integer.parseInt(x.getCarAxis()))
                        .collect(Collectors.toSet());
            }
        }
        //查询车辆轴数
        Map<Integer, TmsTruckAxleNum> tmsTruckAxleNumMap  = Maps.newHashMap();
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(carAxis)){
            List<TmsTruckAxleNum> tmsTruckAxleNums = kwfTruckAxleNumRepository.queryByIds(carAxis);
            tmsTruckAxleNumMap = Optional.ofNullable(tmsTruckAxleNums)
                    .orElse(List.of())
                    .stream()
                    .collect(Collectors.toMap(TmsTruckAxleNum::getId, Function.identity(), (k1, k2) -> k1));
        }

        Map<Long, List<KwfFleetTruck>> finalFleetIdAndKwfFleetTruckList = fleetIdAndKwfFleetTruckList;
        Map<Long, KwfTruck> finalTruckIdAndTruckMap = truckIdAndTruckMap;
        Map<Integer, TmsTruckAxleNum> finalTmsTruckAxleNumMap = tmsTruckAxleNumMap;
        List<QueryFleetResp> fleets = records.stream()
                .map(item -> getQueryFleetResp(item, userIdAndUserCacheResDtoMap, finalFleetIdAndKwfFleetTruckList, finalTruckIdAndTruckMap, finalTmsTruckAxleNumMap))
                .toList();
        return PageDataResult.of(page, fleets);
    }
    private Set<Long> getAllEnt(QueryFleetReq req) {
        Set<Long> allEnt = Sets.newHashSet();
        //根据企业类型查询企业
        if (StringUtils.isBlank(req.getEntId())){
            req.setEntId(String.valueOf(LoginUserHolder.getEntId()));
        }

        if (StringUtils.isBlank(req.getEntId())){
            return allEnt;
        }
        allEnt.add( Long.parseLong(req.getEntId()));
        EntCacheResDto entCacheResDto = remoteSystemService.queryEntTreeById(Long.parseLong(req.getEntId()));
        if (Objects.nonNull(entCacheResDto)) {
            EntCacheResDto entCacheResDto1 = remoteSystemService.queryEntTreeById(entCacheResDto.getId());
            List<EntCacheResDto> child = entCacheResDto1.getChild();
            if (CollectionUtils.isNotEmpty(child)) {
                allEnt.addAll(child.stream().map(EntCacheResDto::getId).toList());
            }
        }
        return allEnt;
    }

    @NotNull
    private static QueryFleetResp getQueryFleetResp(KwfFleet item,
                                                    Map<Long, UserCacheResDto> userIdAndUserCacheResDtoMap,
                                                    Map<Long, List<KwfFleetTruck>> finalFleetIdAndKwfFleetTruckList,
                                                    Map<Long, KwfTruck> truckIdAndTruckMap,
                                                    Map<Integer, TmsTruckAxleNum> tmsTruckAxleNumMap) {
        QueryFleetResp fleet = new QueryFleetResp();
        fleet.setId(item.getId());
        fleet.setEntId(item.getEntId());
        fleet.setCaptainId(item.getCaptainId());
        UserCacheResDto userCacheResDto = userIdAndUserCacheResDtoMap.getOrDefault(item.getCaptainId(), new UserCacheResDto());
        fleet.setCaptainName(userCacheResDto.getName());
        fleet.setName(item.getName());
        fleet.setContacts(item.getContacts());
        fleet.setPhone(item.getPhone());
        fleet.setCreateBy(String.valueOf(item.getCreateBy()));
        UserCacheResDto createUser = userIdAndUserCacheResDtoMap.getOrDefault(item.getCreateBy(),
                new UserCacheResDto());
        fleet.setCreateByName(createUser.getName());
        fleet.setCreateTime(DateUtils.format(item.getCreateTime(),DateUtils.DATE_TIME_PATTERN));
        fleet.setUpdateTime(DateUtils.format(item.getUpdateTime(),DateUtils.DATE_TIME_PATTERN));
        fleet.setRemark(item.getRemark());
        List<KwfFleetTruck> trucks = finalFleetIdAndKwfFleetTruckList.getOrDefault(item.getId(), new ArrayList<>());
        List<QueryFleetResp.TruckInfo> truckInfos = trucks.stream()
                .map(x -> getTruckInfo(truckIdAndTruckMap, x,tmsTruckAxleNumMap))
                .collect(Collectors.toList());
        fleet.setTruckInfo(truckInfos);
        fleet.setTruckNum(trucks.size());

        return fleet;
    }

    private static QueryFleetResp.TruckInfo getTruckInfo(Map<Long, KwfTruck> truckIdAndTruckMap, KwfFleetTruck x,Map<Integer, TmsTruckAxleNum> tmsTruckAxleNumMap) {
        QueryFleetResp.TruckInfo truckInfo = new QueryFleetResp.TruckInfo();
        KwfTruck truck = truckIdAndTruckMap.getOrDefault(x.getTruckId(), new KwfTruck());
        TmsTruckAxleNum truckAxleNum = tmsTruckAxleNumMap.getOrDefault(Integer.parseInt(truck.getCarAxis()), new TmsTruckAxleNum());
        truckInfo.setTruckId(truck.getId());
        truckInfo.setTruckNo(truck.getTruckNo());
        truckInfo.setAxleNum(truckAxleNum.getName());
        truckInfo.setType(truck.getType());
        truckInfo.setTypeDesc(TruckTypeEnum.getName(truck.getType()));
        return truckInfo;
    }

    public List<QueryFleetResp> findFleetList(QueryFleetReq req) {
        log.info("查询车队列表，请求参数：{}", JSON.toJSONString(req));
        Long  entId =  org.apache.commons.lang3.StringUtils.isNotBlank(req.getEntId()) ? Long.valueOf(req.getEntId()) : LoginUserHolder.getEntId();
        List<KwfFleet> fleetByEntId = kwfFleetRepository.findFleetByEntId(entId);
        if (CollectionUtils.isEmpty(fleetByEntId)){
            return Collections.emptyList();
        }
      return fleetByEntId.stream().map(x->{
            QueryFleetResp queryFleetResp = new QueryFleetResp();
            queryFleetResp.setId(x.getId());
            queryFleetResp.setName(x.getName());
            return queryFleetResp;
        }).collect(Collectors.toList());
    }
}
