package com.yeejoin.amos.maintenance.business.service.impl;

import com.yeejoin.amos.maintenance.business.constants.XJConstant;
import com.yeejoin.amos.maintenance.business.dao.mapper.PlanTaskDetailMapper;
import com.yeejoin.amos.maintenance.business.dao.mapper.RouteMapper;
import com.yeejoin.amos.maintenance.business.dao.repository.*;
import com.yeejoin.amos.maintenance.business.param.RoutePageParam;
import com.yeejoin.amos.maintenance.business.service.intfc.IPlanService;
import com.yeejoin.amos.maintenance.business.service.intfc.IPlanTaskService;
import com.yeejoin.amos.maintenance.business.service.intfc.IRouteService;
import com.yeejoin.amos.maintenance.business.util.DaoCriteria;
import com.yeejoin.amos.maintenance.business.vo.PointInputItemVo;
import com.yeejoin.amos.maintenance.core.common.request.CommonPageable;
import com.yeejoin.amos.maintenance.core.common.request.RoutePointInputItemRequest;
import com.yeejoin.amos.maintenance.core.common.response.RoutePointRespone;
import com.yeejoin.amos.maintenance.core.util.query.BaseQuerySpecification;
import com.yeejoin.amos.maintenance.dao.entity.*;
import com.yeejoin.amos.maintenance.exception.YeeException;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service("routeService")
public class RouteServiceImpl implements IRouteService {

    @Autowired
    private IRouteDao iRouteDao;
    @Autowired
    private IPlanDao planDao;

    @Autowired
    private IRoutePointDao iRoutePointDao;

    @Autowired
    private IPointDao iPointDao;

    @Autowired
    private IPointClassifyDao iPointClassifyDao;

    @Autowired
    private IInputItemDao iInputItemDao;

    @Resource
    private RouteMapper routeMapper;

    @Autowired
    private IPointInputItemDao iPointInputItemDao;

    @Autowired
    private IPlanService planService;

    @Autowired
    private IPlanTaskService planTaskService;

    @Autowired
    PlanTaskDetailMapper planTaskDetailMapper;

    @Autowired
    private IRoutePointItemDao iRoutePointItemDao;

    @Autowired
    private IPlanTaskDetailDao iPlanTaskDetailDao;


    @Autowired
    IPlanTaskDao planTaskDao;

    @Override
    @Transactional
    public Route  addRoute(Route route) {
        String creatorId = route.getCreatorId();
        String orgCode = route.getOrgCode();
        route = iRouteDao.saveAndFlush(route);
        Long rId = route.getId();
        List<RoutePoint> routePoints = route.getRoutePointList();
        routePoints.forEach(rp -> {
            rp.setOrgCode(orgCode);
            rp.setRouteId(rId);
            rp.setCreatorId(creatorId);
            List<RoutePointItem> routePointItems = rp.getRoutePointItem();
            rp = iRoutePointDao.saveAndFlush(rp);
            Long rpId = rp.getId();
            routePointItems.forEach(rpi -> {
                rpi.setRoutePointId(rpId);
                rpi.setCreatorId(creatorId);
                iRoutePointItemDao.saveAndFlush(rpi);
            });
        });
        return route;
    }

    @Override
    @Transactional
    public void delRouteById(Long[] ids) {
        //0.删除路线
        iRouteDao.delRouteById(Arrays.asList(ids));
        // 1.停用关联计划
        planService.disablePlan(ids);
        // 2.停用关联计划任务
        planTaskService.disablePlanTask(ids);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Route updateRoute(Route route) {
        List<RoutePoint> routePoints = route.getRoutePointList();
        route = iRouteDao.saveAndFlush(route);
        Long routeId = route.getId();
        String orgCode = route.getOrgCode();
        String creatorId = route.getCreatorId();
        Route finalRoute = route;
        routePoints.forEach(rp -> {
            rp.setOrgCode(orgCode);
            rp.setRouteId(routeId);
            rp.setCreatorId(creatorId);
            if (rp.getIsDelete()) {
                iRoutePointItemDao.delRoutePointItem(rp.getId());
                iRoutePointDao.deleteById(rp.getId());
                //删除p_plan_task_detail 对应点、更新p_plan_task点数量、完成数量
                this.updatePlanTask(rp.getPointId(),finalRoute.getId());
            } else {
                List<RoutePointItem> routePointItems = rp.getRoutePointItem();
                iRoutePointDao.saveAndFlush(rp);
                Long rpId = rp.getId();
                List<Long> delRoutePointItemIds = new ArrayList<>();
                if (routePointItems != null && !routePointItems.isEmpty()) {
                    AtomicInteger num = new AtomicInteger(1);
                    routePointItems.forEach(rpi -> {
                        rpi.setOrderNo(num.getAndIncrement());
                        if (!rpi.getIsBound()) {
                            delRoutePointItemIds.add(rpi.getId());
                        } else {
                            rpi.setRoutePointId(rpId);
                            rpi.setCreatorId(creatorId);
                            iRoutePointItemDao.save(rpi);
                        }
                    });
                    delRoutePointItemIds.remove(null);
                    delRoutePointItemIds.remove(0L);
                    if (!delRoutePointItemIds.isEmpty()) {
                        iRoutePointItemDao.deleteByRoutePointItemId(delRoutePointItemIds);
                    }
                }
            }
        });
        return route;
    }

    private void updatePlanTask(long pointId, long routeId) {
        List<PlanTask> planTaskList = planTaskDao.findByRouteId(routeId);
        List<PlanTaskDetail> planTaskDetailList = iPlanTaskDetailDao.findByPointId(pointId);
        Map<Long,PlanTask> planTaskMap = planTaskList.stream().collect(Collectors.toMap(BasicEntity::getId, Function.identity()));
        for (PlanTaskDetail planTaskDetail : planTaskDetailList) {
            PlanTask planTask = planTaskMap.get(planTaskDetail.getTaskNo());
            if (1 == planTaskDetail.getIsFinish()) {
                planTask.setFinishNum(planTask.getFinishNum() - 1);
                planTask.setPointNum(planTask.getPointNum() - 1);
            } else {
                planTask.setPointNum(planTask.getPointNum() - 1);
            }
        }
        //更新主表完成数量，点数量
        planTaskDao.saveAll(planTaskList);
        //删除路线下的维保点
        planTaskDetailMapper.deleteByPointIdAndRouteId(pointId, routeId);
    }


    @Override
    @Transactional(rollbackFor = {YeeException.class, Exception.class})
    public void migrateRoutePoint(Long sourceRouteId, Long[] pointIds, Long targetRouteId) {
        List<RoutePoint> routePointList = iRoutePointDao.queryRoutePoint(sourceRouteId, pointIds);
        if (routePointList.isEmpty()) {
            throw new YeeException("点数据不存在");
        }
        List<Long> targetPointIds = iRoutePointDao.findAllByRouteId(targetRouteId);
        List<Long> targetPointDelIds = new ArrayList<>();
        List<Long> ids = new ArrayList<>();
        for (RoutePoint routePoint : routePointList) {
            if (targetPointIds.contains(routePoint.getPointId())) {
                targetPointDelIds.add(routePoint.getPointId());
            }
            ids.add(routePoint.getId());
            routePoint.setRouteId(targetRouteId);
        }
        iRoutePointDao.saveAll(routePointList);
        if (!targetPointDelIds.isEmpty()) {
            iRoutePointDao.deleteByRouteIdAndPointIdInAndIdNotIn(targetRouteId, targetPointDelIds, ids);
        }
    }

    @Override
    public Route queryRouteById(Long id) {
        return iRouteDao.findById(id).get();
    }

    @Override
    public Page<Route> queryRouteInfo(List<DaoCriteria> criterias, CommonPageable commonPageable) {
        BaseQuerySpecification<Route> spec = new BaseQuerySpecification<>(criterias);
        return iRouteDao.findAll(spec, commonPageable);
    }

    @Override
    public List<RoutePointRespone> queryRoutePoints(Long routeId) {
        Map<String, Object> param = new HashMap<>();
        param.put("routeId", routeId);
        return routeMapper.queryRoutePointsByCondition(param);
    }

    @Override
    public int countRoutePoint(Long routeId) {
        int routePointCount = iRoutePointDao.countRoutePoint(routeId);
        return routePointCount;
    }

    @Override
    public List<Long> queryRoutePointIds(Long routeId) {
        return iRoutePointDao.queryRoutePointIds(routeId);
    }

    @Override
    @Transactional
    public void addRoutePoint(List<RoutePoint> routePointList) {
        int size = iRoutePointDao.maxRoutePointOrderNo(routePointList.get(0).getRouteId()) + 1;
        List<RoutePoint> pointList = new ArrayList<>();
        //1.更新点的路线信息
        for (RoutePoint routePoint : routePointList) {
            Long pointId = routePoint.getPointId();
            Long routeId = routePoint.getRouteId();
            routePoint.setOrderNo(size);
            size = size + 1;
            pointList.add(routePoint);
            Point point = iPointDao.findById(pointId).get();
            Route route = iRouteDao.findById(routeId).get();
            String routeIds = point.getRouteId();
            String routeNames = point.getRouteName();
            if (routeIds != null && routeIds != "") {
                String[] routeIdsStr = routeIds.split(",");
                List<String> list = Arrays.asList(routeIdsStr);

                if (!list.contains(String.valueOf(routeId))) {
                    routeIds = routeIds + "," + routeId;
                    routeNames = routeNames + "," + route.getName();
                }
            } else {
                routeIds = String.valueOf(routeId);
                routeNames = route.getName();
            }
            point.setRouteId(routeIds);
            point.setRouteName(routeNames);
        }//end 更新点的路线信息
        iRoutePointDao.saveAll(pointList);
    }

    @Override
    @Transactional
    public void deleteRoutePoint(Long routeId, Long[] pointIds) {
        List<RoutePoint> routePointList = iRoutePointDao.queryRoutePoint(routeId, pointIds);
        for (RoutePoint routePoint : routePointList) {    //更新点的路线信息
            Long pointId = routePoint.getPointId();
            Point point = iPointDao.findById(pointId).get();
            Route route = iRouteDao.findById(routeId).get();
            String routeIds = point.getRouteId();
            String routeNames = point.getRouteName();
            if (null != routeIds && "" != routeIds) {
                String[] routeIdsStr = routeIds.split(",");
                String[] routeNameStr = routeNames.split(",");
                List<String> idList = new ArrayList<String>(routeIdsStr.length);
                Collections.addAll(idList, routeIdsStr);
                List<String> nameList = new ArrayList<String>(routeNameStr.length);
                Collections.addAll(nameList, routeNameStr);
                if (idList.contains(String.valueOf(routeId))) {
                    idList.remove(String.valueOf(routeId));
                    nameList.remove(route.getName());
                }
                routeIds = StringUtils.join(idList.toArray(), ",");
                routeNames = StringUtils.join(nameList.toArray(), ",");
            }
            point.setRouteId(routeIds);
            point.setRouteName(routeNames);
            iRoutePointDao.deleteById(routePoint.getId());
        }
    }


    @Override
    public List<PointInputItemVo> listRoutePointInputItem(Long routeId, Long pointId) {
        List<PointInputItemVo> inputItemList = routeMapper.getInputItemById(routeId, pointId);
        return inputItemList;
    }

    @Override
    @Transactional
    public void updateRoutePointInputItem(Long routeId, Long pointId, Long[] inputItemIds) {
        Long[] pointIds = {pointId};
        String creatorId = "";
        long routePointId = 0;
        RoutePoint routePoint = null;
        // 1.先查找并删除表中已有的行（旧的项）
        List<RoutePoint> oldRoutePointList = iRoutePointDao.queryRoutePoint(routeId, pointIds);
        if (oldRoutePointList.size() > 0) {
            routePoint = oldRoutePointList.get(0);

            creatorId = routePoint.getCreatorId();
            routePointId = routePoint.getId();
        }
        iRoutePointItemDao.delRoutePointItem(routePointId);

        // 2.保存新的项到数据库
        List<RoutePointItem> routePointList = new ArrayList<>();
        int orderNo = 0;
        for (Long inputItemId : inputItemIds) {
            PointInputItem pointInputItem = iPointInputItemDao.getPointInputItem(pointId, inputItemId);
            RoutePointItem routePointItem = new RoutePointItem();
            routePointItem.setCreatorId(creatorId);
            routePointItem.setOrderNo(orderNo++);
            routePointItem.setPointInputItemId(pointInputItem.getId());
            routePointItem.setRoutePointId(routePointId);
            routePointItem.setRoutePoint(routePoint);

            routePointList.add(routePointItem);
        }
        iRoutePointItemDao.saveAll(routePointList);
    }

    @Override
    public List<Route> queryRouteInfo(List<DaoCriteria> criterias) {
        BaseQuerySpecification<Route> spec = new BaseQuerySpecification<>(criterias);
        return iRouteDao.findAll(spec);
    }

    @Override
    public Map<String, List<InputItem>> listRoutePointInputItemWithClassify(Long routeId, Long pointId) {
        Map<String, List<InputItem>> classifyInputItemMap = new HashMap<>();
        List<PointInputItem> pointInputItemList = routeMapper.getRoutePointInputItem(routeId, pointId);        // 路线点项列表
        List<PointClassify> pointClassifyList = iPointClassifyDao.getPointClassifyByPointId(pointId);    //点分类列表

        for (PointClassify pointClassify : pointClassifyList) {
            List<InputItem> inputItemList = new ArrayList<>();
            for (PointInputItem pointInputItem : pointInputItemList) {
                if (pointInputItem.getClassifyIds().contains(String.valueOf(pointClassify.getId()))) {
                    inputItemList.add(iInputItemDao.findById(pointInputItem.getInputItemId()).get());
                }
            }
            classifyInputItemMap.put(pointClassify.getName(), inputItemList);
        }
        return classifyInputItemMap;
    }

    @Override
    public Page<HashMap<String, Object>> getRouteInfo(String toke, String product, String appKey, RoutePageParam params) {
        long total = routeMapper.countRoute(params);
        List<HashMap<String, Object>> content = routeMapper.getRouteInfo(params);
        return new PageImpl<>(content, params, total);
    }

    @Override
    public List<Plan> queryPlanByRouteId(long routeId) {
        List<Plan> list = planDao.queryPlanByRouteId(routeId, XJConstant.PLAN_STATUS_START);
        return list;
    }

    @Override
    public List<HashMap<String, Object>> queryRouteListByOrgCode(String orgCode, String userId, String deptId) {
        return routeMapper.queryRouteListByOrgCode(orgCode, userId, deptId);
    }

    @Override
    public void exchangeRoutePointOrderNumber(long src, long target) {
        List<Long> ids = new ArrayList<>();
        ids.add(src);
        ids.add(target);
        List<RoutePoint> points = iRoutePointDao.findAllById(ids);
        int srcNo = points.get(0).getOrderNo();
        int targetNo = points.get(1).getOrderNo();
        points.get(0).setOrderNo(targetNo);
        points.get(1).setOrderNo(srcNo);
        iRoutePointDao.saveAll(points);
    }

    @Override
    public List<Long> getPointIDByRouyeId(Long routeID) {
        List<Long> list = iRoutePointDao.queryRoutePointIds(routeID);
        return list;
    }

    @Override
    public LinkedHashMap<String, Object> getPointIdByRouteId(List<String> routeIds) {
        LinkedHashMap<String, Object> routePointIdMap = new LinkedHashMap<>();
        for (String routeId : routeIds) {
            List<String> pointIDS = iRoutePointDao.getRoutePointIds(routeId);
//			List<String> pointIds = new ArrayList<>();
//			for (Long pointId : pointIDS) {
//				pointIds.add(pointId.toString());
//			}
            routePointIdMap.put(routeId.toString(), pointIDS);
        }
        return routePointIdMap;
    }

    @Override
    public List<HashMap<String, Object>> listRoutePointInputItem(RoutePointInputItemRequest request) {
        return routeMapper.queryRoutePointItemByCondition(request);
    }

    @Override
    public boolean existRouteName(String orgCode, String name) {
        long count = iRouteDao.countAllByOrgCodeAndName(orgCode, name);
        if (count > 0) {
            return true;
        }
        return false;
    }

    @Override
    public List<Route> queryRouteList(String ownerId, String orgCode) {
        // TODO Auto-generated method stub
        return routeMapper.queryRoutesByOrgCode(ownerId, orgCode);
    }
}
