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

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
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.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.pojo.build.dto.BuildDto;
import com.tofly.pojo.build.vo.BuildVo;
import com.tofly.pojo.build.vo.BulidclearVo;
import com.tofly.pojo.build.vo.detail.*;
import com.tofly.pojo.plan.dto.ReportAuditDto;
import com.tofly.pojo.plan.vo.PlanchildVo;
import com.tofly.pojo.plan.vo.RecordVo;
import com.tofly.gpsboot.exception.BusinessException;
import com.tofly.gpsboot.mapper.build.BuildMapper;
import com.tofly.gpsboot.service.build.BuildService;
import com.tofly.gpsboot.service.build.BuildplanService;
import com.tofly.gpsboot.service.build.BuildtypeService;
import com.tofly.gpsboot.service.build.BulidclearService;
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.RecordService;
import com.tofly.gpsboot.service.report.IReportConstructionSiteServer;
import com.tofly.gpsboot.util.DateTimeUtil;
import com.tofly.pojo.User;
import com.tofly.pojo.build.Build;
import com.tofly.pojo.build.Buildplan;
import com.tofly.pojo.build.Bulidclear;
import com.tofly.pojo.plan.Plan;
import com.tofly.pojo.plan.Planchild;
import com.tofly.pojo.plan.Record;
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("buildService")
public class BuildServiceImpl extends ServiceImpl<BuildMapper, Build> implements BuildService {
    @Autowired
    private UserClent userClent;
    @Autowired
    private BuildtypeService buildtypeService;
    @Autowired
    private BuildplanService buildplanService;
    @Autowired
    private BulidclearService bulidclearService;
    @Autowired
    private PlanService planService;
    @Autowired
    private PlanchildService planchildService;
    @Autowired
    private PlanInspectGroupService planInspectGroupService;
    @Autowired
    private PlanInspectUserService planInspectUserService;
    @Autowired
    private IFileInfoService iFileInfoService;
    @Value("${xrty.ftp.build}")
    private String buildFilePath;

    @Autowired
    private IReportConstructionSiteServer iReportConstructionSiteServer;

    @Autowired
    private RecordService recordService;

    @Autowired
    private PeriodService periodService;

    @Autowired
    private DepartmentClient departmentClient;

    @Autowired
    private IDisposeDateService iDisposeDateService;

    @Override
    public List<BuildVo> viewConversion(List<Build> infoList) {
        List<BuildVo> infoVoList = new ArrayList<>();
        infoList.forEach(info -> {
            BuildVo baseInfo = JSONObject.parseObject(JSON.toJSONString(info), BuildVo.class);
            // 新增工地类型名称/ 转换隐患上报途径/是否需人员巡查/隐患状态/是否接收查看/上报状态/审核结果
            Long typeId = info.getTypeId();
            if (null != typeId && 0 != typeId) {
                baseInfo.setType(buildtypeService.getById(typeId).getName());
            }

            baseInfo.setUploadType(TroubleReportTypeEnum.getCodeForValue(info.getUploadType()));
            baseInfo.setIsrespect(IsRespectEnum.getCodeForValue(info.getIsrespect()));
            baseInfo.setState(TroubleSateEnum.getCodeForValue(info.getState()));
            baseInfo.setIsread(IsReadEnum.getCodeForValue(info.getIsread() + ""));
            baseInfo.setIsSubmit(IsSubmitEnum.getCodeForValue(info.getIsSubmit()));
            baseInfo.setAuditResult(IsAuditEnum.getCodeForValue(info.getAuditResult()));
            // 添加审核人名称/上报人名称
            Long auditUser = info.getAuditUser();
            Long submitUser = info.getSubmitUser();
            if (null != auditUser && 0 != auditUser) {
                User userAudit = userClent.getById(auditUser).getResult();
                if(null!=userAudit){
                    baseInfo.setAuditUserName(userAudit.getRealName());
                }

            }
            if (null != submitUser && 0 != submitUser) {
                User userSubmit = userClent.getById(submitUser).getResult();
                if(null!=userSubmit){
                    baseInfo.setSubmitUserName(userSubmit.getRealName());
                }

            }
            if (!StringUtils.isEmpty(info.getUploadFileids())) {
                baseInfo.setFilePathList(iFileInfoService.getFilePathList(Arrays.stream(info.getUploadFileids().split(Constant.CSV)).map(s -> Long.parseLong(s.trim()))
                        .collect(Collectors.toList())));
            }
            infoVoList.add(baseInfo);
        });

        return infoVoList;

    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void savaBuildInfo(List<MultipartFile> fileList, BuildDto parDto) {
        Build build = JSONObject.parseObject(JSON.toJSONString(parDto), Build.class);
        // 判断当前是否有文件,则存入返回文件id
        if (null != fileList && fileList.size() > 0) {
            StringBuilder fileIdList = iFileInfoService.saveFileList(fileList, buildFilePath, FileTableEnum.TF_YWPN_BUILD_W.getTableName());
            // 根据文件id反射填充对象
            build.setUploadFileids(fileIdList.toString());
        }

        // 对象入库
        this.save(build);
        // 自动上报
        ReportAuditDto dto = new ReportAuditDto();
        dto.setId(build.getId());
        dto.setBuildNotes(build.getNotes());
        dto.setAuditId(build.getAuditUser());
        iReportConstructionSiteServer.report(dto);
    }

    @Override
    public BuildDetailVo getBuildInfoDetail(Long id, String flag) {
        BuildDetailVo buildDetailVo = new BuildDetailVo();
        // 获取工地信息
        Build build = this.getById(id);
        // 获取子计划信息
        List<PlanchildVo> planchildVo = this.getPlanChildVo(id, flag);
        // 子计划添加
        buildDetailVo.setPlanchildVoList(planchildVo);
        // 工地监护结束信息
        buildDetailVo.setBulidclearVoList(this.getBulidclearVo(build.getId()));
        // 工地巡查记录
        if(null!=planchildVo && planchildVo.size()>0){
            Set<Long> collect = planchildVo.stream().map(PlanchildVo::getId).collect(Collectors.toSet());
            buildDetailVo.setRecordVoList(this.getBuildRecordVo(collect));
        }

        // 工地监护派工信息
        buildDetailVo.setBuildDispatchingVo(this.getBuildDispatchingVo(build));
        // 工地信息
        List<Build> list = new ArrayList<>();
        list.add(build);
        buildDetailVo.setBuildVo(this.viewConversion(list).get(0));


        return buildDetailVo;
    }

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

        // 当前部门下用户才有权限
        Long departmentId = SecurityUtils.getUser().getDepartmentId();
        List<Long> userIdList = departmentClient.getDeptUserList(String.valueOf(departmentId)).getResult().stream().map(User::getId).collect(Collectors.toList());

        Set<Long> selSet = new HashSet<>(this.list(new QueryWrapper<Build>().lambda().in(Build::getCreateUser, userIdList)).stream().map(Build::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 = buildplanService.list(new QueryWrapper<Buildplan>().lambda().in(Buildplan::getPlanId, collect)).stream().map(Buildplan::getBuildId).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);
        }

        if (!StringUtils.isEmpty(auditResults)) {
            List<String> longList = Arrays.stream(auditResults.split(Constant.CSV)).collect(Collectors.toList());
            wrapper.in("AUDIT_RESULT", longList);
            build.setAuditResult(null);
        }

        wrapper.setEntity(build);
        String address = parDto.getAddress();
        if(!StringUtils.isEmpty(address)){
            wrapper.like("ADDRESS", address);
        }
        wrapper.orderByDesc("CREATE_TIME").orderByDesc("AUDIT_TIME");
        Page infoPageList = this.page(page, wrapper);
        infoPageList.setRecords(this.viewConversion(infoPageList.getRecords()));
        return infoPageList;
    }

    @Override
    public void updateBuildInfo(List<MultipartFile> fileList, BuildDto parDto) throws BusinessException {
        if (!iDisposeDateService.isDisposePermissions(parDto.getCreateUser())) {
            throw new BusinessException(Constant.IS_DISPOSE_PERMISSIONS_NULL_CODE, Constant.IS_DISPOSE_PERMISSIONS_NULL);

        }
        Build updateRecord = JSONObject.parseObject(JSON.toJSONString(parDto), Build.class);
        List<Long> fileIdLongList = new ArrayList<>();
        if (null != fileList && fileList.size() > 0) {
            StringBuilder fileIdList = iFileInfoService.saveFileList(fileList, buildFilePath, FileTableEnum.TF_YWPN_BUILD_W.getTableName());
            fileIdLongList = Arrays.stream(fileIdList.toString().split(Constant.CSV)).map(s -> Long.parseLong(s.trim()))
                    .collect(Collectors.toList());
        }
        Build 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
    public void deleteBuildInfo(List<Long> idList) throws BusinessException {
        List<Long> removeFileIdList = new ArrayList<>();
        idList.forEach(info -> {
            Build 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<PlanchildVo> 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(String.valueOf(departmentId)).getResult().stream().map(User::getId).collect(Collectors.toSet());
            longSet.addAll(collect);
        } else {
            longSet.add(user.getUserid());
        }
        List<Buildplan> buildPlans = buildplanService.list(new QueryWrapper<Buildplan>().lambda().eq(Buildplan::getBuildId, 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 planchildService.viewConversion(planChildList);
        }
        return null;
    }


    /**
     * 工地监护记录
     *
     * @param planChildIdList
     * @return
     */
    private List<RecordVo> getBuildRecordVo(Set<Long> planChildIdList) {
        List<Record> list = recordService.list(new QueryWrapper<Record>().lambda().in(Record::getPlanChildid, planChildIdList));
        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 BuildDispatchingVo getBuildDispatchingVo(Build trouble) {
        BuildDispatchingVo processVo = new BuildDispatchingVo();
        String auditResult = trouble.getAuditResult();
        Long auditUser = trouble.getAuditUser();
        // 判断当前审核是否通过
        if (AuditSateEnum.AUDIT_YES.getCode().equals(auditResult)) {
            // 根据隐患id,去隐患与计划关联表查询到计划id
            // 再查询对应计划信息
            // 再根据计划id的巡检组,巡检人
            List<Buildplan> buildplans = buildplanService.list(new QueryWrapper<Buildplan>().lambda().eq(Buildplan::getBuildId, 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;
    }


    /**
     * 工地监护消除审核
     *
     * @param bulidId
     * @return
     */
    private List<BulidclearVo> getBulidclearVo(Long bulidId) {
        List<Bulidclear> bulidClearList = bulidclearService.list(new QueryWrapper<Bulidclear>().lambda().eq(Bulidclear::getBuildId, bulidId));
        if (null != bulidClearList && bulidClearList.size() > 0) {
            List<BulidclearVo> bulidclearVoList = bulidclearService.viewConversion(bulidClearList);
            bulidclearVoList.sort(Comparator.comparing(BulidclearVo::getSubmitTime).reversed());
            return bulidclearVoList;
        }

        return null;

    }

}
