package com.njcn.device.line.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.device.biz.pojo.dto.LineDevGetDTO;
import com.njcn.device.biz.pojo.dto.SubGetBase;
import com.njcn.device.biz.pojo.dto.TerminalGetBase;
import com.njcn.device.biz.pojo.param.SubstationParam;
import com.njcn.device.line.mapper.DeptLineMapper;
import com.njcn.device.line.mapper.LineDetailMapper;
import com.njcn.device.line.mapper.LineMapper;
import com.njcn.device.line.service.DeptLineService;
import com.njcn.device.pq.pojo.po.DeptLine;
import com.njcn.device.pq.pojo.po.LineDetail;
import com.njcn.device.pq.pojo.vo.DevDetailVO;
import com.njcn.device.pq.pojo.vo.LineDeviceStateVO;
import com.njcn.device.userledger.service.UserLedgerService;
import com.njcn.supervision.pojo.vo.user.NewUserReportVO;
import com.njcn.system.api.DictTreeFeignClient;
import com.njcn.system.enums.DicTreeEnum;
import com.njcn.system.pojo.vo.DictTreeVO;
import com.njcn.user.api.DeptFeignClient;
import com.njcn.user.pojo.dto.DeptDTO;
import com.njcn.user.pojo.po.Dept;
import com.njcn.web.pojo.param.DeptLineParam;
import com.njcn.web.utils.WebUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * @author denghuajun
 * @date 2022/1/12 17:32
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class DeptLineServiceImpl extends ServiceImpl<DeptLineMapper, DeptLine> implements DeptLineService {

    private final DeptLineMapper deptLineMapper;
    private final DeptFeignClient deptFeignClient;
    private final LineMapper lineMapper;
    private final DictTreeFeignClient dictTreeFeignClient;
    private final LineDetailMapper detailMapper;
    private final UserLedgerService userLedgerService;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deptBindLine(DeptLineParam deptLineParam) {
        //先解绑，再进行绑定
        QueryWrapper<DeptLine> deptLineQueryWrapper = new QueryWrapper<>();
        deptLineQueryWrapper.eq("pq_dept_line.id", deptLineParam.getId());
        this.baseMapper.delete(deptLineQueryWrapper);
        List<DeptLine> deptLines = deptLineParam.getIds().stream().map(id -> {
            DeptLine deptLine = new DeptLine();
            deptLine.setId(deptLineParam.getId());
            deptLine.setLineId(id);
            return deptLine;
        }).collect(Collectors.toList());
        List<String> ids = deptLineParam.getIds();
        if (CollUtil.isNotEmpty(ids)) {
            List<LineDetail> list = detailMapper.selectList(new LambdaQueryWrapper<LineDetail>()
                    .in(LineDetail::getId, ids)
                    .isNull(LineDetail::getActualArea)
            );
            if (CollUtil.isNotEmpty(list)) {
                Dept data = deptFeignClient.getDeptById(deptLineParam.getId()).getData();
                List<String> lineIds = list.stream().map(LineDetail::getId).collect(Collectors.toList());
                detailMapper.update(null, new LambdaUpdateWrapper<LineDetail>()
                        .set(LineDetail::getActualArea, data.getArea())
                        .in(LineDetail::getId, lineIds));
            } else {
                List<String> deptList = Arrays.asList("130700000000", "130300000000", "130800000000", "130200000000", "131000000000");
                Dept data = deptFeignClient.getDeptById(deptLineParam.getId()).getData();
                if (deptList.contains(data.getArea())) {
                    detailMapper.update(null, new LambdaUpdateWrapper<LineDetail>()
                            .set(LineDetail::getActualArea, data.getArea())
                            .in(LineDetail::getId, ids));
                }
            }
        }
        this.saveBatch(deptLines);
    }

    @Override
    public void deptDeleteBindLine(DeptLineParam deptLineParam) {
        for (int i = 0; i < deptLineParam.getIds().size(); i++) {
            QueryWrapper<DeptLine> deptLineQueryWrapper = new QueryWrapper<>();
            deptLineQueryWrapper.eq("pq_dept_line.id", deptLineParam.getId());
            deptLineQueryWrapper.eq("pq_dept_line.Line_Id", deptLineParam.getIds().get(i));
            this.baseMapper.delete(deptLineQueryWrapper);
        }
    }

    @Override
    public List<DeptLine> selectDeptBindLines(List<String> ids) {
        return this.lambdaQuery().in(DeptLine::getId, ids).list();
    }

    @Override
    public List<DeptLine> selectDeptLine(List<String> ids) {
        List<DeptLine> list = this.lambdaQuery().in(DeptLine::getLineId, ids).list();
        if (CollUtil.isNotEmpty(list)) {
            List<Dept> data = deptFeignClient.getAllDept().getData();
            Map<String, String> deptName = data.stream().collect(Collectors.toMap(Dept::getId, Dept::getName));
            for (DeptLine deptLine : list) {
                if (deptName.containsKey(deptLine.getId())) {
                    deptLine.setId(deptName.get(deptLine.getId()));
                }
            }
            return list;
        }
        return new ArrayList<>();
    }

    @Override
    public List<String> getLineByDeptIds(List<String> ids,String manufacturer, List<Integer> runFlag, List<Integer> dataType, String objType) {
        return this.baseMapper.getLineIdByDeptIds(ids, manufacturer ,runFlag, dataType, objType);
    }

    @Override
    public int removeBind(String id) {
        QueryWrapper<DeptLine> deptLineQueryWrapper = new QueryWrapper<>();
        deptLineQueryWrapper.eq("pq_dept_line.id", id);
        return this.baseMapper.delete(deptLineQueryWrapper);
    }

    @Override
    public List<String> getLineByDeptId(String id) {
        return this.lambdaQuery().in(DeptLine::getId, id).list().stream().map(DeptLine::getLineId).distinct().collect(Collectors.toList());
    }

    @Override
    public List<String> getLineByDeptIdAndNewStation(String id) {
        List<String> dictTree = new ArrayList<>();
        DictTreeVO powerStation = dictTreeFeignClient.queryByCode(DicTreeEnum.Power_Station.getCode()).getData();
        if (ObjectUtil.isNotNull(powerStation)) {
            dictTree.add(powerStation.getId());
        }
        DictTreeVO windFarms = dictTreeFeignClient.queryByCode(DicTreeEnum.Wind_Farms.getCode()).getData();
        if (ObjectUtil.isNotNull(windFarms)) {
            dictTree.add(windFarms.getId());
        }
        if (CollUtil.isNotEmpty(dictTree)) {
            List<String> ids = new ArrayList<>();
            if (StrUtil.isNotBlank(id)) {
                ids.addAll(deptFeignClient.getDepSonIdtByDeptId(id).getData());
            }
            return this.baseMapper.getLineByDeptIdAndNewStation(ids, dictTree);
        }
        return new ArrayList<>();
    }

    @Override
    public List<String> getLineNodeByDeptId(String id) {
        List<DeptDTO> deptInfos = deptFeignClient.getDeptDescendantIndexes(id, WebUtil.filterDeptType()).getData();
        List<String> deptIds = deptInfos.stream().map(DeptDTO::getId).distinct().collect(Collectors.toList());
        List<DeptLine> userLine = this.list(new LambdaQueryWrapper<DeptLine>()
                .in(DeptLine::getId, deptIds)
        );
        return userLine.stream().map(DeptLine::getLineId).distinct().collect(Collectors.toList());
    }

    /**
     * @param devDataType
     * @Description: 获取部门和监测点的关系（分稳态暂态）
     * @Param: [devDataType]
     * @return: java.util.Map<java.lang.String, java.util.List < java.lang.String>>
     * @Author: clam
     * @Date: 2022/10/19
     */
    @Override
    public Map<String, List<String>> getLineByDeptRelation(Integer devDataType) {
        List<DeptLine> deptLines = deptLineMapper.getLineByDeptRelation(devDataType);
        return deptLines.stream().collect(Collectors.groupingBy(DeptLine::getId, Collectors.mapping(DeptLine::getLineId, Collectors.toList())));
    }

    @Override
    public Map<String, List<LineDevGetDTO>> lineDevGet(List<Integer> devDataType, Integer type, Integer lineRunFlag) {
        List<LineDevGetDTO> deptLines = deptLineMapper.lineDevGet(devDataType, type, lineRunFlag);
        return deptLines.stream().collect(Collectors.groupingBy(LineDevGetDTO::getUnitId));
    }

    @Override
    public Map<String, List<LineDevGetDTO>> lineDevAllGet(List<Integer> devDataType, Integer type, Integer lineRunFlag, Integer lineType) {
        List<LineDevGetDTO> deptLines = deptLineMapper.lineDevAllGet(devDataType, type, lineRunFlag,lineType);
        return deptLines.stream().collect(Collectors.groupingBy(LineDevGetDTO::getUnitId));
    }

    @Override
    public Map<String, List<TerminalGetBase>> orgSubStationGet(List<Integer> devDataType) {
        List<TerminalGetBase> deptLines = deptLineMapper.orgSubStationGet(devDataType);
        return deptLines.stream().collect(Collectors.groupingBy(TerminalGetBase::getUnitId));
    }

    @Override
    public List<TerminalGetBase.Extend> orgSubStationInfoGet(List<Integer> devType,
                                                             Integer powerFlag,
                                                             Integer lineRunFlag,
                                                             Integer monitorFlag,
                                                             String searchValue
    ) {
        return deptLineMapper.orgSubStationInfoGet(devType, powerFlag, lineRunFlag,monitorFlag,searchValue);
    }

    @Override
    public List<SubGetBase> getSubStationList(SubstationParam substationParam) {
        return deptLineMapper.selectSubStationList(substationParam);
    }

    @Override
    public DeptLine getLineByLineIds(String ids) {
        return this.getOne(new LambdaQueryWrapper<DeptLine>()
                .eq(DeptLine::getLineId, ids)
        );
    }

    @Override
    public List<DeptLine> getDeptListByLineId(String id) {
        return this.list(new LambdaQueryWrapper<DeptLine>()
                .eq(DeptLine::getLineId, id));
    }

    @Override
    public List<LineDeviceStateVO> getLineDetailByDeptId(String id) {
        List<String> lineByDeptId = this.getLineNodeByDeptId(id);
        List<LineDeviceStateVO> lineDeviceStateVO = lineMapper.getLineDeviceStateVO(lineByDeptId);
        return lineDeviceStateVO;
    }

    @Override
    public List<DevDetailVO> getLineDetailByDeptIdAndDevIds(String orgId,Integer powerFlag, List<String> devIds) {
        List<String> lineByDeptId = this.getLineNodeByDeptId(orgId);
        List<DevDetailVO> lineDeviceByDevIds = lineMapper.getLineDeviceByDevIds(powerFlag,lineByDeptId, devIds);
        if(CollUtil.isNotEmpty(lineDeviceByDevIds)){
            List<String> objIds = lineDeviceByDevIds.stream()
                    .filter(x -> StrUtil.isNotBlank(x.getObjId()))
                    .map(DevDetailVO::getObjId)
                    .distinct()
                    .collect(Collectors.toList());
            if(CollUtil.isNotEmpty(objIds)){
                List<NewUserReportVO> data = userLedgerService.getUserReportByIds(objIds);
                Map<String, String> userMap = data.stream().collect(Collectors.toMap(NewUserReportVO::getId, NewUserReportVO::getProjectName));
                for (DevDetailVO lineDeviceByDevId : lineDeviceByDevIds) {
                    if(StrUtil.isNotBlank(lineDeviceByDevId.getObjId())){
                        if(userMap.containsKey(lineDeviceByDevId.getObjId())){
                            lineDeviceByDevId.setSubName(userMap.get(lineDeviceByDevId.getObjId()));
                        }
                    }
                }
            }
        }
        return lineDeviceByDevIds;
    }


}
