/*
 * Author: Zev
 * 生成ServiceImpl
 */
package com.tofly.gpsboot.service.trouble.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.tofly.api.DepartmentClient;
import com.tofly.api.UserClent;
import com.tofly.common.core.util.StringUtil;
import com.tofly.common.oauth.auth.ToflyUser;
import com.tofly.common.oauth.util.SecurityUtils;
import com.tofly.gpsboot.common.Constant;
import com.tofly.gpsboot.common.system.*;
import com.tofly.gpsboot.service.trouble.*;
import com.tofly.pojo.build.Build;
import com.tofly.pojo.build.Bulidclear;
import com.tofly.pojo.plan.dto.ReportAuditDto;
import com.tofly.pojo.plan.vo.PlanchildVo;
import com.tofly.pojo.plan.vo.RecordVo;
import com.tofly.pojo.trouble.dto.TroubleDto;
import com.tofly.pojo.trouble.vo.ToubleclearVo;
import com.tofly.pojo.trouble.vo.detail.*;
import com.tofly.pojo.trouble.vo.TroubleVo;
import com.tofly.gpsboot.exception.BusinessException;
import com.tofly.gpsboot.mapper.trouble.TroubleMapper;
import com.tofly.gpsboot.service.build.BuildService;
import com.tofly.gpsboot.service.comm.IDisposeDateService;
import com.tofly.gpsboot.service.comm.IFileInfoService;
import com.tofly.gpsboot.service.config.PeriodService;
import com.tofly.gpsboot.service.paln.task.PlanInspectGroupService;
import com.tofly.gpsboot.service.paln.task.PlanInspectUserService;
import com.tofly.gpsboot.service.paln.task.PlanService;
import com.tofly.gpsboot.service.paln.task.PlanchildService;
import com.tofly.gpsboot.service.process.PointtempService;
import com.tofly.gpsboot.service.process.RecordService;
import com.tofly.gpsboot.service.report.IReportHiddenTroubleServer;
import com.tofly.gpsboot.util.DateTimeUtil;
import com.tofly.pojo.User;
import com.tofly.pojo.plan.Plan;
import com.tofly.pojo.plan.Planchild;
import com.tofly.pojo.plan.Record;
import com.tofly.pojo.trouble.Toubleclear;
import com.tofly.pojo.trouble.Toubleplan;
import com.tofly.pojo.trouble.Toubletype;
import com.tofly.pojo.trouble.Trouble;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

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


/**
 * 隐患上报信息表
 *
 * @author admin
 * @date Thu Mar 18 00:00:00 CST 2021
 */
@Service("troubleService")
public class TroubleServiceImpl extends ServiceImpl<TroubleMapper, Trouble> implements TroubleService {

    @Autowired
    private ToubletypeService toubletypeService;
    @Autowired
    private UserClent userClent;
    @Autowired
    private BuildService buildService;
    @Autowired
    private PlanService planService;
    @Autowired
    private ToubleplanService toubleplanService;
    @Autowired
    private PlanInspectGroupService planInspectGroupService;
    @Autowired
    private PlanInspectUserService planInspectUserService;
    @Autowired
    private ToubleclearService toubleclearService;
    @Autowired
    private IFileInfoService iFileInfoService;
    @Value("${xrty.ftp.trouble}")
    private String troubleFilePath;
    @Autowired
    private IReportHiddenTroubleServer iReportHiddenTroubleServer;
    @Autowired
    private PointtempService pointtempService;
    @Autowired
    private PlanchildService planchildService;
    @Autowired
    private RecordService recordService;

    @Autowired
    private PeriodService periodService;

    @Autowired
    private DepartmentClient departmentClient;
    @Autowired
    private IDisposeDateService iDisposeDateService;

    @Autowired
    private ToublerangeService toublerangeService;

    @Override
    public TroubleDetailVo getTroubleInfoDetail(Long id, String flag) {
        TroubleDetailVo troubleDetailVo = new TroubleDetailVo();
        // 获取隐患信息
        Trouble trouble = this.getById(id);
        // 获取子计划信息
        List<Planchild> planchildVoList = this.getPlanChildVo(id, flag);
        // 子计划添加
        troubleDetailVo.setPlanchildVoList(planchildVoList);
        // 隐患消除信息
        troubleDetailVo.setTroubleClearVoList(this.getTroubleClearVo(trouble.getId()));
        // 隐患巡查记录
        if (null != planchildVoList && planchildVoList.size() > 0) {
            Set<Long> collect = planchildVoList.stream().map(Planchild::getId).collect(Collectors.toSet());
            troubleDetailVo.setRecordVoList(this.getToubleRecordVo(collect));
        }
        // 隐患派工信息
        troubleDetailVo.setTroubleDispatchingVo(this.getTroubleDispatchingVo(trouble));
        // 隐患信息
        troubleDetailVo.setTroubleVo(trouble);

        return troubleDetailVo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void savaBuildInfo(List<MultipartFile> fileList, TroubleDto parDto) {
        StringBuilder fileIdList = new StringBuilder("");
        // 判断当前是否有文件,则存入返回文件id
        if (null != fileList && fileList.size() > 0) {
            fileIdList = iFileInfoService.saveFileList(fileList, troubleFilePath, FileTableEnum.TF_YWPN_TROUBLE_W.getTableName());

        }
        // 根据文件id反射填充对象
        Trouble info = JSONObject.parseObject(JSON.toJSONString(parDto), Trouble.class);
        info.setUploadFileids(fileIdList.toString());
        if(StringUtil.isEmpty(info.getState())){
          info.setState(TroubleSateEnum.TROUBLE_SATE_REPORT.getCode());
        }
        // 对象入库
        this.save(info);
        // 自动上报
        ReportAuditDto dto = new ReportAuditDto();
        dto.setId(info.getId());
        dto.setTroubleNotes(info.getNotes());
        dto.setAuditId(info.getAuditUser());
        iReportHiddenTroubleServer.report(dto);
    }

    @Override
    public Page<Trouble> getBuildPage(Page page, TroubleDto parDto) {
        // 审批状态 , 分割查询
        String auditResults = parDto.getAuditResults();
        Trouble build = JSONObject.parseObject(JSON.toJSONString(parDto), Trouble.class);
        QueryWrapper<Trouble> wrapper = new QueryWrapper();

        // 当前部门下用户才有权限
        ToflyUser user = SecurityUtils.getUser();
        Long departmentId = user.getDepartmentId();
        List<Long> userIdList = departmentClient.getDeptUserList(departmentId).getResult().stream().map(User::getId).collect(Collectors.toList());
        if (!StringUtils.isEmpty(auditResults)) {
            List<String> longList = Arrays.stream(auditResults.split(Constant.CSV)).collect(Collectors.toList());
            wrapper.in("AUDIT_RESULT", longList);
            build.setAuditResult(null);
        }
        Set<Long> selSet = new HashSet<>(this.list(new QueryWrapper<Trouble>().lambda().in(Trouble::getCreateUser, userIdList)).stream().map(Trouble::getId).collect(Collectors.toSet()));

        if(!StringUtils.isEmpty(parDto.getFlag())){
            Set<Long> collect = planchildService.list(new QueryWrapper<Planchild>().lambda().eq(Planchild::getRespUser, SecurityUtils.getUserId())).stream().map(Planchild::getPlanId).collect(Collectors.toSet());
            if(collect.size()>0){
                Set<Long> collect1 = toubleplanService.list(new QueryWrapper<Toubleplan>().lambda().in(Toubleplan::getPlanId, collect)).stream().map(Toubleplan::getTroubleId).collect(Collectors.toSet());
                if(collect1.size()>0){
                    wrapper.in("ID",collect1);
                }else {
                    wrapper.in("ID",0L);
                }
            }else {
                wrapper.in("ID",0L);
            }

        }else {
            if(selSet.size()>0){
                wrapper.in("ID", selSet);
            }else {
                wrapper.in("ID",0L);
            }

        }
        String state = parDto.getState();
        if(!StringUtils.isEmpty(state)){
            List<String> longList = Arrays.stream(state.split(Constant.CSV)).collect(Collectors.toList());
            wrapper.in("STATE",longList);
            build.setState(null);
        }
        // 上报时间范围查询
        Date startTime = parDto.getStartDate();
        Date endTime = parDto.getEndDate();
        if(null!=startTime  && null!=endTime){
            wrapper.ge("SUBMIT_TIME",startTime);
            wrapper.le("SUBMIT_TIME",endTime);
        }

        wrapper.setEntity(build);
        String address = parDto.getAddress();
        if(!StringUtils.isEmpty(address)){
            wrapper.like("ADDRESS", address);
            build.setAddress(null);
        }

        wrapper.orderByDesc("CREATE_TIME").orderByDesc("AUDIT_TIME");
        Page infoPageList = this.page(page, wrapper);

        List<Trouble> infoList= infoPageList.getRecords();
       if(infoList!=null){
        infoList.forEach(info -> {//特殊状态，监护巡查，不显示审核状态

            List<Toubleclear> clearList=toubleclearService.list(Wrappers.<Toubleclear>lambdaQuery()
                    .eq(Toubleclear::getToubleId,info.getId()).orderByDesc(Toubleclear::getSubmitTime));

            if(clearList!=null &&clearList.size()>0){
                Toubleclear toubleclear=clearList.get(0);
                if(toubleclear!=null && StringUtil.isNotEmpty(toubleclear.getAuditResult())){
                    info.setAuditNotes(toubleclear.getAuditNotes());
                    info.setAuditResult(toubleclear.getAuditResult());
                }
                //未审核,找上次的审核结果
                if(toubleclear.getAuditTime()==null){
                    if(clearList.stream().filter(a->a.getAuditTime()!=null).count()>0){
                        //找到审核数据，赋值
                        Toubleclear toubleclearMax=clearList.stream().filter(a->a.getAuditTime()!=null).max(Comparator.comparing(Toubleclear::getAuditTime)).get();
                        info.setAuditNotes(toubleclearMax.getAuditNotes());
                    }
                }
                String  AuditResultName= AuditSateEnum.getCodeForValue(info.getAuditResult());
                info.setAuditResultName(AuditResultName);
            }
            if(info.getState()!=null && info.getState().equals(TroubleSateEnum.TROUBLE_SATE_PATROL.getCode())){
                info.setAuditResultName("");
            }
        });

       }

        return infoPageList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateTroubleInfo(List<MultipartFile> fileList, TroubleDto parDto) throws BusinessException {
        if (!iDisposeDateService.isDisposePermissions(parDto.getCreateUser())) {
            throw new BusinessException(Constant.IS_DISPOSE_PERMISSIONS_NULL_CODE, Constant.IS_DISPOSE_PERMISSIONS_NULL);

        }
        Trouble updateRecord = JSONObject.parseObject(JSON.toJSONString(parDto), Trouble.class);
        List<Long> fileIdLongList = new ArrayList<>();
        if (null != fileList && fileList.size() > 0) {
            StringBuilder fileIdList = iFileInfoService.saveFileList(fileList, troubleFilePath, FileTableEnum.TF_YWPN_TROUBLE_W.getTableName());
            fileIdLongList = Arrays.stream(fileIdList.toString().split(Constant.CSV)).map(s -> Long.parseLong(s.trim()))
                    .collect(Collectors.toList());
        }
        Trouble record = this.getById(parDto.getId());
        String lostFileIds = record.getUploadFileids();
        String fileIds = parDto.getUploadFileids();
        List<Long> removeFileId = new ArrayList<>();
        List<Long> fileIdLongs = new ArrayList<>();
        if (!StringUtils.isEmpty(fileIds)) {
            fileIdLongs = Arrays.stream(fileIds.split(Constant.CSV)).map(s -> Long.parseLong(s.trim()))
                    .collect(Collectors.toList());
        }
        // 判断当前文件是否有更新
        if (!StringUtils.isEmpty(lostFileIds)&&lostFileIds.equals(fileIds)) {
            List<Long> lostFileIdLongs = Arrays.stream(lostFileIds.split(Constant.CSV)).map(s -> Long.parseLong(s.trim()))
                        .collect(Collectors.toList());

            List<Long> finalFileIdLongs = fileIdLongs;
            lostFileIdLongs.forEach(lost -> {
                if (!finalFileIdLongs.contains(lost)) {
                    removeFileId.add(lost);
                }
            });
            // 删除对应文件数据
            if (removeFileId.size() > 0) {
                // 删除远程文件
                iFileInfoService.removeFileList(removeFileId);
            }
            if (lostFileIdLongs.size() > 0) {
                // 删除远程文件
                iFileInfoService.removeFileList(lostFileIdLongs);
            }

        }
        // 更新数据信息
        fileIdLongList.addAll(fileIdLongs);
        if (fileIdLongList.size() > 0) {
            StringBuilder stringBuilder = new StringBuilder("");
            fileIdLongList.forEach(info -> {
                stringBuilder.append(info).append(Constant.CSV);
            });
            updateRecord.setUploadFileids(stringBuilder.deleteCharAt(stringBuilder.length() - 1).toString());
            this.updateById(updateRecord);
            return;
        }
        this.updateById(updateRecord);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteTroubleInfo(List<Long> idList) throws BusinessException {
        List<Long> removeFileIdList = new ArrayList<>();
        idList.forEach(info -> {
            Trouble record = this.getById(info);
            if (!iDisposeDateService.isDisposePermissions(record.getCreateUser())) {
                throw new BusinessException(Constant.IS_DISPOSE_PERMISSIONS_NULL_CODE, Constant.IS_DISPOSE_PERMISSIONS_NULL);

            }
            String fileIds = record.getUploadFileids();
            if (!StringUtils.isEmpty(fileIds)) {
                List<Long> fileIdLongs = Arrays.stream(fileIds.split(Constant.CSV)).map(s -> Long.parseLong(s.trim()))
                        .collect(Collectors.toList());
                removeFileIdList.addAll(fileIdLongs);
            }
        });
        if (removeFileIdList.size() > 0) {
            // 删除远程文件
            iFileInfoService.removeFileList(removeFileIdList);
        }
        this.removeByIds(idList);
    }

    private List<Planchild> getPlanChildVo(Long id, String flag) {
        Set<Long> longSet = new HashSet<>();
        ToflyUser user = SecurityUtils.getUser();
        // 若flag为空则查询当前用户的子任务
        if (IsOverEnum.IS_OVER_NO.getCode().equals(flag)) {
            Long departmentId = user.getDepartmentId();
            Set<Long> collect = departmentClient.getDeptUserList(departmentId).getResult().stream().map(User::getId).collect(Collectors.toSet());
            longSet.addAll(collect);
        } else {
            longSet.add(user.getUserid());
        }
        List<Toubleplan> buildPlans = toubleplanService.list(new QueryWrapper<Toubleplan>().lambda().eq(Toubleplan::getTroubleId, id));
        List<Planchild> planChildList = new ArrayList<>();
        if (null != buildPlans && buildPlans.size() > 0) {
            // 获取当前时间下的巡检计划
            LocalDateTime time = DateTimeUtil.getTodayBeginTime();
            buildPlans.forEach(info -> {
                Long planId = info.getPlanId();
                if (IsOverEnum.IS_OVER_NO.getCode().equals(flag)) {
                    List<Planchild> list = planchildService.list(new QueryWrapper<Planchild>().lambda()
                            .eq(Planchild::getPlanId, planId)
                            .in(Planchild::getRespUser, longSet));
                    planChildList.addAll(list);

                } else {
                    // 判断当前时间 在那个计划时间范围内
                    Plan plan = planService.getById(planId);
                    LocalDateTime beginDate = DateTimeUtil.fromLong2LocalDateTime(plan.getPlanBegindate().getTime());
                    LocalDateTime endDate = DateTimeUtil.fromLong2LocalDateTime(plan.getPlanEnddate().getTime());
                    if (beginDate.compareTo(time) <= 0 && endDate.compareTo(time) >= 0) {
                        List<Planchild> list = planchildService.list(new QueryWrapper<Planchild>().lambda()
                                .eq(Planchild::getPlanId, planId)
                                .in(Planchild::getRespUser, longSet));
                        planChildList.addAll(list);
                    }

                }


            });
        }
        if (planChildList.size() > 0) {
            return planChildList;
        }
        return null;
    }

    /**
     * 隐患消除审核
     *
     * @param troubleId
     * @return
     */
    private List<ToubleclearVo> getTroubleClearVo(Long troubleId) {
        List<Toubleclear> bulidClearList = toubleclearService.list(new QueryWrapper<Toubleclear>().lambda().eq(Toubleclear::getToubleId, troubleId));
        if (null != bulidClearList && bulidClearList.size() > 0) {
            List<ToubleclearVo> bulidclearVoList = toubleclearService.viewConversion(bulidClearList);
            bulidclearVoList.sort(Comparator.comparing(ToubleclearVo::getSubmitTime).reversed());
            return bulidclearVoList;
        }

        return null;

    }

    /**
     * 隐患上报记录
     *
     * @param collect
     * @return
     */
    private List<RecordVo> getToubleRecordVo(Set<Long> collect) {
        List<Record> list = recordService.list(new QueryWrapper<Record>().lambda().in(Record::getPlanChildid, collect));
        if (null != list && list.size() > 0) {
            List<RecordVo> recordVoList = recordService.viewConversion(list);
            recordVoList.sort(Comparator.comparing(RecordVo::getCreateTime).reversed());
            return recordVoList;
        }
        return null;
    }


    /**
     * 隐患信息
     *
     * @param trouble
     * @return
     */
    private TroubleDispatchingVo getTroubleDispatchingVo(Trouble trouble) {
        TroubleDispatchingVo processVo = new TroubleDispatchingVo();
        String auditResult = trouble.getAuditResult();
        Long auditUser = trouble.getAuditUser();
        // 判断当前审核是否通过
        if (AuditSateEnum.AUDIT_YES.getCode().equals(auditResult)) {
            // 根据隐患id,去隐患与计划关联表查询到计划id
            // 再查询对应计划信息
            // 再根据计划id的巡检组,巡检人
            List<Toubleplan> buildplans = toubleplanService.list(new QueryWrapper<Toubleplan>().lambda().eq(Toubleplan::getTroubleId, trouble.getId()));
            if (null != buildplans && buildplans.size() > 0) {
                Long planId = buildplans.get(0).getPlanId();
                Plan planInfo = planService.getById(planId);
                Long periodId = planInfo.getPeriodId();
                processVo.setPeriodId(periodId);
                processVo.setPeriodName(periodService.getById(periodId).getPeriodName());
                processVo.setInterValDay(planInfo.getIntervalDay());
                processVo.setInspectGroupIdName(planInspectGroupService.getInspectGroupName(planId));
                processVo.setInspectUserName(planInspectUserService.getInspectUserList(planId));
                processVo.setPlanBegindate(planInfo.getPlanBegindate());
                processVo.setPlanEnddate(planInfo.getPlanEnddate());
            }
            processVo.setAuditUser(auditUser);
            User result = userClent.getById(auditUser).getResult();
            if(null!=result){
                processVo.setAuditUserName(result.getRealName());
            }

            processVo.setAuditResult(IsAuditEnum.getCodeForValue(trouble.getAuditResult()));
            processVo.setIsrespect(IsRespectEnum.getCodeForValue(trouble.getIsrespect()));

        }

        return processVo;
    }


}
