package cn.cslg.report.service.business;

import cn.cslg.report.common.core.base.Constants;
import cn.cslg.report.common.model.vo.PersonnelVO;
import cn.cslg.report.common.model.vo.ReportVO;
import cn.cslg.report.common.model.vo.SystemDictVO;
import cn.cslg.report.common.utils.*;
import cn.cslg.report.common.utils.SecurityUtils.LoginUtils;
import cn.cslg.report.common.utils.SecurityUtils.SecurityUtils;
import cn.cslg.report.common.utils.auth.checkAuth;
import cn.cslg.report.entity.Personnel;
import cn.cslg.report.entity.Report;

import cn.cslg.report.entity.ReportFiles;
import cn.cslg.report.entity.asso.AssoReportFile;
import cn.cslg.report.mapper.ReportMapper;
import cn.cslg.report.service.IAvoidDesignDirectionService;
import cn.cslg.report.service.IProductService;
import cn.cslg.report.service.OutInterfaceService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
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 io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.models.security.SecurityScheme;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
@RequiredArgsConstructor(onConstructor_ = {@Lazy})
@SuppressWarnings({"all"})
public class ReportService extends ServiceImpl<ReportMapper, Report> {
    private final OutInterfaceService outInterfaceService;
    private final ReportMapper reportMapper;
    private final ReportFieldService reportFieldService;
    private final CacheUtils cacheUtils;
    private final LoginUtils loginUtils;
    private final AssoReportFileService assoReportFileService;
    private final ReportFileService reportFileService;
    private final AssoTaskPersonelService assoTaskPersonelService;
    private final TaskService taskService;
    private final FeatureService featureService;
    private final CompareScenariosService compareScenariosService;
    private final IProductService productService;
    private final IAvoidDesignDirectionService avoidDesignDirectionService;
    private final CompareFilesService compareFilesService;
    private final CompareMessageService compareMessageService;
    private final ImportTaskService importTaskService;
    private final InvalidRecordService invalidRecordService;
    private final ReportDocumentService reportDocumentService;
    private final ReportReferencesService reportReferencesService;

    /**
     * @param report 报告类
     * @author 沈永艺
     */
    @Transactional(rollbackFor = Exception.class)
    public Integer addReport(Report report, List<MultipartFile> files) {
        try {
            report.getScenarioList();
            report.setScenarioId(StringUtils.join(report.getScenarioList(), ","));
            if (report.getAssociateReportId() != null) {
                LambdaQueryWrapper<Report> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(Report::getId, report.getAssociateReportId());
                Report assioReport = this.list(wrapper).get(0);
                report.setAssociateReportName(assioReport.getName());
            }
            PersonnelVO personnelVO = cacheUtils.getLoginUser(loginUtils.getId());
            report.setCreatePersonId(personnelVO.getId());
            //如果报告类型是4(侵权分析报告)则将状态设为2(处理中)
            if (report.getType().equals(4)) {
                report.setStatus(2);
            }
            boolean addFlag = this.save(report);

            if (files != null && files.size() != 0) {
                //将文档上传并返回文件入库的Id
                List<Integer> fileIds = reportFileService.uploadFiles(files);
                assoReportFileService.addAsso(report.getId(), fileIds);
            }
            //如果报告生成成功，给报告添加默认自定义字段
            if (addFlag) {
                reportFieldService.addDefaultField(report.getId(), report.getType());
                return report.getId();
            } else {
                return 0;
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("新增报告异常，异常信息:" + LogExceptionUtil.getMessage(e));
            log.info("新增报告功能异常，开始回滚! 时间: " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            log.info("回滚完毕! 时间: " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            return -1;
        } finally {
            // TODO: 2022/11/4 这个Finally可以引入表日志记录 或者做点别的什么 也可以删掉
            System.out.println("报告新增结束");
        }
    }

    //    @Transactional(rollbackFor = Exception.class)
    //查询报告
    public String queryReport(ReportVO reportVO) throws IOException {
        Integer id = loginUtils.getId();
        List<Integer> departIds = outInterfaceService.getDutyDepartsFromPCS(id);
        LambdaQueryWrapper<Report> queryWrapper = new LambdaQueryWrapper<>();
        if (reportVO.getName() != null) {
            queryWrapper.like(Report::getName, reportVO.getName());
        }
        if (reportVO.getReportId() != null) {
            queryWrapper.eq(Report::getId, reportVO.getReportId());
        }
        if (reportVO.getSignPatentNo() != null && reportVO.getSignPatentNo() != "") {
            queryWrapper.like(Report::getSignPatentNo, reportVO.getSignPatentNo());
        }
        queryWrapper.orderByDesc(Report::getCreateTime);
        //分页
        if (reportVO.getSize() != null && reportVO.getCurrent() != null) {
            SecurityUtils.startDataScope("/pcs/report/query");
            List<Report> reports = this.page(new Page<>(reportVO.getCurrent(), reportVO.getSize()), queryWrapper).getRecords();
            reports = this.reportData(reports);
            SecurityUtils.startDataScope("/pcs/report/query");
            Long  count = this.count(queryWrapper);
            return Response.success(reports, DataUtils.setPageColumn(reportVO.getSize(), reportVO.getCurrent(), Math.toIntExact(count)));
        } else {
            SecurityUtils.startDataScope("/pcs/report/query");
            List<Report> reports = this.list(queryWrapper);
            SecurityUtils.startDataScope("/pcs/report/query");
            long count = this.count(queryWrapper);
            reports = this.reportData(reports);
            return Response.success(reports, DataUtils.setPageColumn(0, 0, Math.toIntExact(count)));
        }
    }

    /**
     * @param reports
     * @return
     * @throws IOException
     * @function 查询报告
     */
    public List<Report> reportData(List<Report> reports) throws IOException {
        //提出报告Id
        List<Integer> reportIds = reports.stream().map(Report::getId).collect(Collectors.toList());
        // 提出客户Id
        List<Integer> clientIds = reports.stream().map(Report::getClientId).collect(Collectors.toList());
        //提出部门Id
        List<Integer> departIds = reports.stream().map(Report::getDepartmentId).collect(Collectors.toList());
        //提出人员Id
        List<Integer> personIds = reports.stream().map(Report::getPersonId).collect(Collectors.toList());
        //提出创建人Id
        List<Integer> createIds = reports.stream().map(Report::getCreatePersonId).collect(Collectors.toList());
        personIds.addAll(createIds);
        //根据报告ID查询报告文件关联信息
        List<AssoReportFile> assoReportFiles = assoReportFileService.queryFileByReportId(reportIds);
        List<ReportFiles> reportFilesList = new ArrayList<>();
        if (assoReportFiles.size() != 0) {
            List<Integer> fileIds = assoReportFiles.stream().map(AssoReportFile::getFileId).collect(Collectors.toList());
            reportFilesList = reportFileService.getFiles(fileIds);
        }
        String res = outInterfaceService.getDictsFromPAS();
        JSONObject jsonObject = JSONObject.parseObject(res);
        List<SystemDictVO> list = JSONArray.parseArray(jsonObject.getString("data"), SystemDictVO.class);
        List<ReportFiles> temList = reportFilesList;
        //根据人员Id获得人员信息
        String res1 = outInterfaceService.getPersonnelByIdsFromPCS(personIds);
        JSONObject jsonObject1 = JSONObject.parseObject(res1);
        //解析jason获得标的专利的权要
        List<Personnel> personnels = JSON.parseArray(jsonObject1.getString("data"), Personnel.class);
        //根据部门Id 获得部门信息
        List<Map<String, Object>> mapDeparts = new ArrayList<>();
        if (departIds.size() != 0) {
            String res2 = outInterfaceService.getDeparts(departIds);
            mapDeparts = JSONObject.parseArray(res2);
        }
        //根据客户Id 获得客户信息
        List<Map<String, Object>> mapClients = new ArrayList<>();
        if (clientIds.size() != 0) {
            String res3 = outInterfaceService.getClientNameFromPAS(clientIds);
            mapClients = JSONObject.parseArray(res3);
        }
        //过滤报告
        for (Report item : reports) {
            //装载创建人名和负责人名
            List<Personnel> mapCre = personnels.stream().filter(tem -> tem.getId().equals(item.getCreatePersonId())).collect(Collectors.toList());
            List<Personnel> mapDuty = personnels.stream().filter(tem -> tem.getId().equals(item.getPersonId())).collect(Collectors.toList());
            if (mapDuty.size() != 0)
                item.setPersonName(mapDuty.get(0).getPersonnelName());
            if (mapCre.size() != 0)
                item.setCreatePersonName(mapCre.get(0).getPersonnelName());
            //装载部门名
            List<Map<String, Object>> mapDeaprt = mapDeparts.stream().filter(tem -> tem.get("departId").toString().equals(item.getDepartmentId().toString())).collect(Collectors.toList());
            if (mapDeaprt.size() != 0) {
                item.setDepartmentName(mapDeaprt.get(0).get("departName").toString());
            }
            //装载客户
            List<Map<String, Object>> mapClient = mapClients.stream().filter(tem -> tem.get("clientId").toString().equals(item.getClientId().toString())).collect(Collectors.toList());
            if (mapClient.size() != 0) {
                item.setClientName(mapClient.get(0).get("clientName").toString());
            }
            //装载报告应用场景
            if (StringUtils.isNotEmpty(item.getScenarioId())) {
                item.setScenarioList(StringUtils.changeStringToString(item.getScenarioId(), ","));
                item.setScenarioNames(list.stream().filter(systemDict -> systemDict.getType().equals(Constants.ENTERPRISE_APPLICATION_SCENARIO) && item.getScenarioList().contains(systemDict.getValue())).map(SystemDictVO::getLabel).collect(Collectors.toList()));
                item.setScenarioId(null);
            }
            //装载报告文件
            List<AssoReportFile> partReportFiles = assoReportFiles.stream().filter(tem -> tem.getReportId().equals(item.getId())).collect(Collectors.toList());
            if (partReportFiles.size() == 0) {
                item.setReportFiles(null);
            } else {
                List<Integer> partFileIds = partReportFiles.stream().map(AssoReportFile::getFileId).collect(Collectors.toList());
                List<ReportFiles> partFiles = temList.stream().filter(tem -> partFileIds.contains(tem.getId())).collect(Collectors.toList());
                item.setReportFiles(partFiles);
            }
        }
        return reports;
    }

    /**
     * @param id(报告id)
     * @return
     * @throws IOException
     * @function 修改报告
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateReport(Report report, List<MultipartFile> files) throws IOException {
        // 根据报告Id查询对应的附件Id
        LambdaQueryWrapper<AssoReportFile> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AssoReportFile::getReportId, report.getId());
        List<AssoReportFile> assoReportFiles = assoReportFileService.list(wrapper);
        List<Integer> fileIds = assoReportFiles.stream().map(AssoReportFile::getFileId).collect(Collectors.toList());
        // 获得报告更新后的附件Id
        List<Integer> updateFileId = new ArrayList<>();
        if (report.getReportFiles() != null) {
            updateFileId = report.getReportFiles().stream().map(ReportFiles::getId).collect(Collectors.toList());
            fileIds.removeAll(updateFileId);
        }
        //做差获得被删除的文件Id
        if (fileIds.size() != 0) {
            //根据文件Id删除报告文件关联表记录
            LambdaQueryWrapper<AssoReportFile> deleteWrapper = new LambdaQueryWrapper<>();
            deleteWrapper.in(AssoReportFile::getFileId, fileIds);
            assoReportFileService.remove(deleteWrapper);
            //根据文件Id删除文件表记录
            reportFileService.removeByIds(fileIds);
        }
//添加附件
        if (files != null && files.size() != 0) {
            //将文档上传并返回文件入库的Id
            List<Integer> fileIdList = reportFileService.uploadFiles(files);
            assoReportFileService.addAsso(report.getId(), fileIdList);
        }
        return report.updateById();

    }

    /**
     * @param id(报告id)
     * @return
     * @throws IOException
     * @function 删除报告
     */
    @Transactional(rollbackFor = Exception.class)
    public String reportDele(int id) throws IOException {
        //删除所有和报告有关的任务
        taskService.deleteTaskByreportId(id);
        //删除所有和报告有关的特征
        featureService.delByReportId(id);
        //删除所有和报告有关的自定义字段
        reportFieldService.deleteByReportId(id);
        //删除所有和报告有关的对比方案
        compareScenariosService.deleteByReportId(id);
        //删除任务人员关联信息表
        assoTaskPersonelService.deleAssoTaskPersonel(id);
        //陈宇 ↓ 删除和报告有关的产品相关数据
        productService.deleteProduct(id);
        //陈宇 ↓ 删除和报告有关的回避设计方案相关数据
        avoidDesignDirectionService.deleteAvoidDesignDirection(id);
        //删除对比文件
        compareFilesService.delete(id);
        //导入删除导入任务
        importTaskService.deleteByRortID(id);

        //删除报告文件导出
        reportDocumentService.deleteByReportId(id);
        //删除报告参考资料
        reportReferencesService.deleteByReportId(id);
        //删除对比信息
        compareMessageService.deleteByreportID(id);


        Boolean dele = this.removeById(id);
        if (dele == true) {
            return Response.success();
        }
        return Response.error("没有数据");
    }

    /**
     * @param id(报告id)
     * @return
     * @throws IOException
     * @function 查询报告
     */

    public String getName(int id) throws IOException {
        LambdaQueryWrapper<Report> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Report::getId, id);
        Report report = this.list(wrapper).get(0);
        return report.getName();

    }

    /**
     * 修改报告的状态
     *
     * @param reportId 报告id
     * @param status   状态
     */
    @Transactional
    public void updateStatus(Integer reportId, Integer status) {
        LambdaQueryWrapper<Report> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Report::getId, reportId);
        Report report = this.list(wrapper).get(0);
        report.setStatus(status);
        report.updateById();

    }


}
