package com.testor.module.accident.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.testor.biz.rule.service.SysRuleService;
import com.testor.biz.sys.dict.data.model.domain.SysDictData;
import com.testor.biz.sys.dict.data.service.SysDictDataService;
import com.testor.biz.sys.dict.type.model.domain.SysDictType;
import com.testor.biz.sys.dict.type.service.SysDictTypeService;
import com.testor.biz.sys.org.model.domain.SysOrg;
import com.testor.biz.sys.org.service.SysOrgService;
import com.testor.biz.sys.user.model.domain.SysUser;
import com.testor.biz.sys.user.service.SysUserService;
import com.testor.biz.util.CacheDicUtils;
import com.testor.common.constant.*;
import com.testor.common.model.UpdateProcessStatusReq;
import com.testor.common.util.DateToUpperUtil;
import com.testor.common.util.EnumUtil;
import com.testor.module.accident.constant.FakeType;
import com.testor.module.accident.dao.AccidentReportDao;
import com.testor.module.accident.manager.AccidentPersonnelManager;
import com.testor.module.accident.model.domain.AccidentPersonnel;
import com.testor.module.accident.model.domain.AccidentReport;
import com.testor.module.accident.model.dto.AccidentReportDetail;
import com.testor.module.accident.model.excel.AccidentExport;
import com.testor.module.accident.model.excel.AccidentExportVO;
import com.testor.module.accident.model.req.*;
import com.testor.module.accident.model.resp.*;
import com.testor.module.accident.model.vo.AccidentPersonnelVO;
import com.testor.module.accident.model.vo.AccidentReportVO;
import com.testor.module.accident.service.AccidentReportService;
import com.testor.module.hazard.model.domain.THazardWorkPlan;
import com.testor.module.hazard.model.dto.ReportDetailParam;
import com.testor.module.video.util.AutoHeadColumnWidthStyleStrategy;
import com.testor.module.video.util.Beans;
import com.tongtech.tfw.backend.common.biz.constants.BizConstants;
import com.tongtech.tfw.backend.common.context.ContextUtils;
import com.tongtech.tfw.backend.common.exception.BusinessException;
import com.tongtech.tfw.backend.common.models.supers.SuperServiceImpl;
import com.tongtech.tfw.backend.common.models.sys.UserInfo;
import com.tongtech.tfw.backend.core.helper.IdHelper;
import com.tongtech.tfw.backend.core.helper.ObjectHelper;
import com.tongtech.tfw.backend.core.helper.StringHelper;
import com.tongtech.tfw.backend.core.helper.bean.BeanHelper;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 事故上报Service业务层处理
 *
 * @author zhangyangfan@testor.com.cn
 * @date 2022-05-11 11:35:33
 */
@Service
public class AccidentReportServiceImpl extends SuperServiceImpl<AccidentReportDao, AccidentReport> implements AccidentReportService {

    @Autowired(required = false)
    private AccidentReportDao accidentReportDao;
    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private SysOrgService sysOrgService;

    @Autowired
    private AccidentPersonnelManager accidentPersonnelManager;

    @Autowired
    private SysDictTypeService sysDictTypeService;

    @Autowired
    private SysDictDataService sysDictDataService;

    @Autowired
    private SysRuleService sysRuleService;


    @Override
    public AccidentReportInsResp insertAll(AccidentReportInsReq accidentReportInsReq) throws Exception {

        if (ObjectHelper.isEmpty(accidentReportInsReq)) {
            throw new BusinessException("请求参数有误，请联系管理员！");
        }
        //获取主键id
        String id = IdHelper.getId32bit();

        accidentReportInsReq.setId(id);
//        accidentReportInsReq.setProcessStatus(ProcessStatus.SUBMIT.getCode());

        //添加消息通知信息(当前创建人)
        accidentReportInsReq.setReceiverType("1");
        accidentReportInsReq.setReceiverObj(ContextUtils.getLoginUserId());

        //赋值创建人部门id
        accidentReportInsReq.setOrgId(ContextUtils.getLoginUser().getOrgId());
        //新增事故报告数据
        accidentReportInsReq.setCreateDate(new Date());
        boolean result = this.save(accidentReportInsReq);
        if (result) {
            if (CollectionUtils.isNotEmpty(accidentReportInsReq.getAccidentPersonnelList())) {
                //处理id及关联id
                accidentReportInsReq.getAccidentPersonnelList().forEach(item -> {
                    item.setId(IdHelper.getId32bit());
                    item.setRefId(id);
                });
                //新增受伤人员
                accidentPersonnelManager.saveBatch(accidentReportInsReq.getAccidentPersonnelList());
            }
        }

        return BeanHelper.beanToBean(accidentReportInsReq, AccidentReportInsResp.class);
    }

    @Override
    public AccidentReportEditResp updateAll(AccidentReportEditReq accidentReportEditReq) throws Exception {
        if (ObjectHelper.isEmpty(accidentReportEditReq) && StringHelper.isEmpty(accidentReportEditReq.getId())) {
            throw new BusinessException("请求参数有误，请联系管理员！");
        }

        this.updateById(accidentReportEditReq);

        //判断请求参数中事故受伤人员信息是否有数据
        if (CollectionUtils.isNotEmpty(accidentReportEditReq.getAccidentPersonnelList())) {
            List<AccidentPersonnel> accidentPersonnelList = accidentReportEditReq.getAccidentPersonnelList();
            List<String> personnelIdList = accidentPersonnelList.stream().filter(item -> StringUtils.isNotBlank(item.getId())).map(AccidentPersonnel::getId).collect(Collectors.toList());
            accidentPersonnelList.stream().forEach(item -> {
                item.setId(IdHelper.getId32bit());
                item.setRefId(accidentReportEditReq.getId());
            });
            //统一删除
            accidentPersonnelManager.deleteBatch(personnelIdList);
            //再全部新增
            accidentPersonnelManager.saveBatch(accidentPersonnelList);
        } else {
            //没有则进行统一删除（可能会出现原先有值的情况）
            accidentPersonnelManager.deleteByRefId(accidentReportEditReq.getId());
        }

        return BeanHelper.beanToBean(accidentReportEditReq, AccidentReportEditResp.class);
    }

    @Override
    public AccidentReportVO getInfo(String id) throws Exception {
        if (StringHelper.isEmpty(id)) {
            throw new BusinessException("请求参数有误，请联系管理员！");
        }
        AccidentReport data = this.getById(id);

        AccidentReportVO accidentReportVO = BeanHelper.beanToBean(data, AccidentReportVO.class);

        SysUser user = sysUserService.getById(accidentReportVO.getCreateBy());

        //赋值上报人手机号
        accidentReportVO.setReporterPhone(user.getPhoneNo());
        //赋值上报人姓名
        accidentReportVO.setReporterName(user.getUserName());

        accidentReportVO.setFakeTypeName(EnumUtil.getByCode(data.getFakeType(), FakeType.class));

        //查询事故受伤人员信息
        List<AccidentPersonnel> accidentPersonnelList = accidentPersonnelManager.lambdaQuery()
                .eq(AccidentPersonnel::getRefId, id).list();

        if (CollectionUtils.isNotEmpty(accidentPersonnelList)) {
            List<AccidentPersonnelVO> accidentPersonnelVOList = accidentPersonnelList.stream().map(item -> {
                AccidentPersonnelVO accidentPersonnelVO = BeanHelper.beanToBean(item, AccidentPersonnelVO.class);
                //中文转换
                accidentPersonnelVO.setSexName(EnumUtil.getByCode(accidentPersonnelVO.getSex(), SexEnum.class));
                accidentPersonnelVO.setBelongTypeName(EnumUtil.getByCode(accidentPersonnelVO.getBelongType(), BelongUnitEnum.class));
                return accidentPersonnelVO;
            }).collect(Collectors.toList());

            //赋值事故受伤人员
            accidentReportVO.setAccidentPersonnelList(accidentPersonnelVOList);
        }

        return accidentReportVO;
    }

    @Override
    public void updateProcessStatus(UpdateProcessStatusReq updateProcessStatusReq) throws Exception {
        if (StringHelper.isEmpty(updateProcessStatusReq.getId()) || StringHelper.isEmpty(updateProcessStatusReq.getProcessStatus())) {
            throw new BusinessException("请求参数有误，请联系管理员！");
        }
        this.lambdaUpdate().set(AccidentReport::getProcessStatus, updateProcessStatusReq.getProcessStatus())
                .set(StringUtils.isNotEmpty(updateProcessStatusReq.getProcessId()), AccidentReport::getProcessId, updateProcessStatusReq.getProcessId())
                .set(StringUtils.isNotEmpty(updateProcessStatusReq.getRejectOpinion()), AccidentReport::getRejectOpinion, updateProcessStatusReq.getRejectOpinion())
                .eq(AccidentReport::getId, updateProcessStatusReq.getId()).update();
    }

    @Override
    public ReportUnitResp getReportUnit() throws Exception {
        UserInfo loginUser = ContextUtils.getLoginUser();
        SysOrg sysOrg = sysOrgService.getById(loginUser.getOrgId());
        if (Objects.isNull(sysOrg)) {
            throw new BusinessException("当前登录人部门信息不存在，请联系管理员！");
        }
        ReportUnitResp reportUnitResp = new ReportUnitResp();

        reportUnitResp.setParentIds(sysOrg.getParentIds() + "," + sysOrg.getOrgId());

        //如果是根节点
        if ("0".equals(sysOrg.getParentId())) {
            reportUnitResp.setFirstLevelDepartmentId(sysOrg.getOrgId());
            reportUnitResp.setFirstLevelDepartment(sysOrg.getOrgName());
            reportUnitResp.setPathIds(sysOrg.getParentIds());
            reportUnitResp.setPath(sysOrg.getOrgName());
            return reportUnitResp;
        }

        String[] parentIds = reportUnitResp.getParentIds().substring(2).split(",");

        reportUnitResp.setFirstLevelDepartmentId(parentIds[0]);
        String lastUnitId = "";
        String lastUnit = "";

        if (parentIds.length == 1) {
            reportUnitResp.setPathIds(parentIds[0]);
        } else if (parentIds.length == 2) {
            reportUnitResp.setPathIds(Arrays.stream(parentIds).collect(Collectors.joining()));
            reportUnitResp.setRegionalCompanyId(parentIds[1]);
        }else {
            // 单位扩展到第4级
            String[] newParents = Arrays.copyOfRange(parentIds, 0, 3);
            reportUnitResp.setPathIds(Arrays.stream(newParents).collect(Collectors.joining()));
            reportUnitResp.setRegionalCompanyId(parentIds[1]);
            reportUnitResp.setBasicUnitId(parentIds[2]);
            if(parentIds.length > 3){
                lastUnitId = parentIds[3];
            }
        }
        List<SysOrg> sysOrgList = sysOrgService.lambdaQuery().in(SysOrg::getOrgId, parentIds).list();

        if (CollectionUtils.isEmpty(sysOrgList) || parentIds.length != sysOrgList.size()) {
            throw new BusinessException("部门信息有误，请联系管理员！");
        }

        //赋值部门名称
        Map<String, String> sysOrgMap = sysOrgList.stream().collect(Collectors.toMap(SysOrg::getOrgId, SysOrg::getOrgName));
        StringBuilder path = new StringBuilder();

        //一级部门名称赋值
        reportUnitResp.setFirstLevelDepartment(sysOrgMap.get(parentIds[0]));
        path.append(sysOrgMap.get(parentIds[0]));

        //赋值区域公司名称
        if (StringUtils.isNotEmpty(reportUnitResp.getRegionalCompanyId())) {
            reportUnitResp.setRegionalCompany(sysOrgMap.get(reportUnitResp.getRegionalCompanyId()));
            path.append("/" + reportUnitResp.getRegionalCompany());
        }

//        if(StringUtils.isNotEmpty(reportUnitResp.getThirdLevelUnitId())){
//            reportUnitResp.setThirdLevelUnit(sysOrgMap.get(reportUnitResp.getThirdLevelUnitId()));
//            path.append("/" + reportUnitResp.getThirdLevelUnit());
//        }

        //赋值基层单位名称
        if (StringUtils.isNotEmpty(reportUnitResp.getBasicUnitId())) {
            reportUnitResp.setBasicUnit(sysOrgMap.get(reportUnitResp.getBasicUnitId()));
            path.append("/" + reportUnitResp.getBasicUnit());
        }

        if(StringUtils.isNotEmpty(lastUnitId)){
            lastUnit = sysOrgMap.get(lastUnitId);
            path.append("/"+lastUnit);
        }

        //赋值路径名称
        reportUnitResp.setPath(path.toString());

        return reportUnitResp;
    }

    @Override
    public AccidentStatisticsResp getAccidentStatistics(AccidentStatisticsReq accidentStatisticsReq) throws Exception {
        ReportUnitResp reportUnit = this.getReportUnit();
        //权限赋值
        if (StringUtils.isNotEmpty(reportUnit.getBasicUnitId())) {
            accidentStatisticsReq.setBasicUnitId(reportUnit.getBasicUnitId());
        }
        if (StringUtils.isNotEmpty(reportUnit.getRegionalCompanyId())) {
            accidentStatisticsReq.setRegionalCompanyId(reportUnit.getRegionalCompanyId());
        }
//        if(StringUtils.isNotEmpty(reportUnit.getThirdLevelUnitId())){
//            accidentStatisticsReq.setThirdLevelUnitId(reportUnit.getThirdLevelUnitId());
//        }
        //数据
        List<AccidentReport> accidentReportList = this.lambdaQuery()
                .eq(StringUtils.isNotBlank(accidentStatisticsReq.getBasicUnitId()), AccidentReport::getBasicUnitId, accidentStatisticsReq.getBasicUnitId())
                .eq(StringUtils.isNotBlank(accidentStatisticsReq.getRegionalCompanyId()), AccidentReport::getRegionalCompanyId, accidentStatisticsReq.getRegionalCompanyId())
                .ge(Objects.nonNull(accidentStatisticsReq.getStartDate()), AccidentReport::getAccidentTime, accidentStatisticsReq.getStartDate())
                .le(Objects.nonNull(accidentStatisticsReq.getEndDate()), AccidentReport::getAccidentTime, accidentStatisticsReq.getEndDate())
                //如果不是基层粮库则只展示状态是已通过的数据
//                .eq(!(StringUtils.isBlank(reportUnit.getBasicUnitId()) && StringUtils.isBlank(reportUnit.getRegionalCompanyId())), AccidentReport::getProcessStatus, ProcessStatus.PASSED.getCode()).list();
//                .eq(StringUtils.isBlank(reportUnit.getBasicUnitId()), AccidentReport::getProcessStatus, ProcessStatus.PASSED.getCode())
                .eq(AccidentReport::getProcessStatus, ProcessStatus.PASSED.getCode())
                .list();

        AccidentStatisticsResp accidentStatisticsResp = new AccidentStatisticsResp();

//        if (CollectionUtils.isEmpty(accidentReportList)) {
//            accidentStatisticsResp.setSource(Boolean.FALSE);
//            return accidentStatisticsResp;
//        } else {
            accidentStatisticsResp.setSource(Boolean.TRUE);
//        }

        switch (accidentStatisticsReq.getStatisticsType()) {
            //组织——柱状图
            case ACCIDENT_ORG:
                //查询组织层级
                int level = 2;
                String orgId = null;
                String parentId = null;
                if (StringUtils.isNotBlank(accidentStatisticsReq.getBasicUnitId())) {
                    level = 3;
                    orgId = accidentStatisticsReq.getBasicUnitId();
                } else if (StringUtils.isNotBlank(accidentStatisticsReq.getRegionalCompanyId())) {
                    level = 3;
                    parentId = accidentStatisticsReq.getRegionalCompanyId();
                }

                //根据条件查询组织信息
                List<SysOrg> sysOrgList = sysOrgService.lambdaQuery()
                        .eq(SysOrg::getTreeLevel, level)
                        .ne(SysOrg::getStatus,BizConstants.STATUS_DELETE)
                        .eq(SysOrg::getIsDept,"0")
                        .eq(StringUtils.isNotBlank(orgId), SysOrg::getOrgId, orgId)
                        .eq(StringUtils.isNotBlank(parentId), SysOrg::getParentId, parentId).orderByAsc(SysOrg::getTreeSort)
                        .notIn(SysOrg::getOrgId,"f241f614bb394762ae4c4aaf33f4f12f")
                        .list();

                AccidentStatisticsResp.Category category = new AccidentStatisticsResp.Category();
//                List<String> xAxis = category.getXAxis();
                List<Map<String, String>> xAxisMap = category.getXAxisMap();
                List<Integer> valueList = category.getValueList();

                Map<String, List<AccidentReport>> accidentReportMap = accidentReportList.stream()
                        .filter(item -> StringUtils.isNotBlank(accidentStatisticsReq.getRegionalCompanyId())
                                || StringUtils.isNotBlank(accidentStatisticsReq.getBasicUnitId())
                                ? StringUtils.isNotEmpty(item.getBasicUnitId())
                                : StringUtils.isNotEmpty(item.getRegionalCompanyId()))
                        .collect(Collectors.groupingBy(e ->
                                //根据当前不同角色进行划分
                                StringUtils.isNotBlank(accidentStatisticsReq.getRegionalCompanyId())
                                        || StringUtils.isNotBlank(accidentStatisticsReq.getBasicUnitId())
                                        ? e.getBasicUnitId() : e.getRegionalCompanyId()));
                sysOrgList.stream().forEach(item -> {
                    Map<String, String> map = new HashMap<>();
                    map.put("name", item.getOrgName());
                    map.put("id", item.getOrgId());
                    map.put("level", item.getTreeLevel().toString());
                    xAxisMap.add(map);
                    //TODO bug
                    List<AccidentReport> accidentReports = accidentReportMap.get(item.getOrgId());
                    valueList.add(CollectionUtils.isNotEmpty(accidentReports) ? accidentReports.size() : 0);
                });

                accidentStatisticsResp.setSource(category);
                Long collect = valueList.stream().collect(Collectors.summingLong(e -> e));
                accidentStatisticsResp.setCount(collect);
                break;
            //月份——柱状图
            case ACCIDENT_MONTH:
                AccidentStatisticsResp.Category categoryByMonth = new AccidentStatisticsResp.Category();

                Map<Integer, List<AccidentReport>> accidentReportByMonthMap = accidentReportList.stream().collect(Collectors.groupingBy(e -> {
                    Calendar cal = Calendar.getInstance();
                    cal.setTime(e.getAccidentTime());
                    int month = cal.get(Calendar.MONTH) + 1;
                    return Integer.valueOf(month);
                }));

                for (int i = 1; i <= 12; i++) {
                    categoryByMonth.getXAxis().add(DateToUpperUtil.monthToUpper(i) + "月");
                    List<AccidentReport> accidentReports = accidentReportByMonthMap.get(i);
                    categoryByMonth.getValueList().add(CollectionUtils.isNotEmpty(accidentReports) ? accidentReports.size() : 0);
                }

                accidentStatisticsResp.setSource(categoryByMonth);
                break;
            //时段——柱状图
            case ACCIDENT_PERIOD:
                AccidentStatisticsResp.Category categoryByHour = new AccidentStatisticsResp.Category();

                Map<Integer, List<AccidentReport>> accidentReportByHourMap = accidentReportList.stream().collect(Collectors.groupingBy(e -> {
//                    Calendar cal = Calendar.getInstance();
//                    cal.setTime(e.getAccidentTime());
//                    int hour = cal.get(Calendar.HOUR);
                    Date accidentTime = e.getAccidentTime();
                    SimpleDateFormat format = new SimpleDateFormat("HH");
                    String hour = format.format(accidentTime);
                    return Integer.valueOf(hour);
                }));

                for (int i = 0; i < 24; i = i + 2) {
                    if (i % 4 == 0) {
                        categoryByHour.getXAxis().add(i + "时~" + (i + 2) + "时");
                    } else {
                        categoryByHour.getXAxis().add("");
                    }
                    List<AccidentReport> accidentReportByHourList = accidentReportByHourMap.get(i);
                    List<AccidentReport> accidentReportByHourAddOneList = accidentReportByHourMap.get(i + 1);

                    //数量相加
                    categoryByHour.getValueList().add(
                            (CollectionUtils.isNotEmpty(accidentReportByHourList) ? accidentReportByHourList.size() : 0)
                                    + (CollectionUtils.isNotEmpty(accidentReportByHourAddOneList) ? accidentReportByHourAddOneList.size() : 0)
                    );
                }

                accidentStatisticsResp.setSource(categoryByHour);
                break;
            //等级——饼图
            case ACCIDENT_LEVEL:
                Map<String, List<AccidentReport>> accidentReportByLevelMap = accidentReportList.stream().collect(Collectors.groupingBy(AccidentReport::getAccidentLevel));

                //查询 事故等级 的数据字典
                SysDictType sysDictType = sysDictTypeService.lambdaQuery().eq(SysDictType::getDictType, DicTypeCode.ACCIDENT_LEVEL.name()).eq(SysDictType::getStatus,"0").list().get(0);

                List<SysDictData> sysDictDataList = sysDictDataService.lambdaQuery().eq(SysDictData::getDictId, sysDictType.getDictId()).eq(SysDictData::getStatus,"0").list();

                List<AccidentStatisticsResp.Pie> pieByLevelList = new ArrayList<>();

                //饼图结构赋值
                sysDictDataList.stream().forEach(item -> {
                    AccidentStatisticsResp.Pie pieByLevel = new AccidentStatisticsResp.Pie();
                    pieByLevel.setName(item.getDictValue());
                    List<AccidentReport> accidentReportByLevelList = accidentReportByLevelMap.get(item.getDictKey());
                    pieByLevel.setValue(CollectionUtils.isNotEmpty(accidentReportByLevelList) ? accidentReportByLevelList.size() : 0);
                    pieByLevelList.add(pieByLevel);
                });

                accidentStatisticsResp.setSource(pieByLevelList);
                break;
            //事故类型——饼图
            case ACCIDENT_TYPE:
                //查询 事故类型 的数据字典
                SysDictType sysDictTypeByAccidentType = sysDictTypeService.lambdaQuery().eq(SysDictType::getDictType, DicTypeCode.ACCIDENT_TYPE.name()).eq(SysDictType::getStatus,"0").list().get(0);

                List<SysDictData> sysDictDataByAccidentTypeList = sysDictDataService.lambdaQuery().eq(SysDictData::getDictId, sysDictTypeByAccidentType.getDictId()).eq(SysDictData::getStatus,"0").list();

                List<AccidentStatisticsResp.Pie> pieByTypeList = new ArrayList<>();

                //事故类型数据饼图结构赋值
                sysDictDataByAccidentTypeList.stream().forEach(item -> {
                    AccidentStatisticsResp.Pie pieByLevel = new AccidentStatisticsResp.Pie();
                    //相应
                    pieByLevel.setName(item.getDictValue());

                    //判断是否包含此类型id
                    long count = accidentReportList.stream().filter(accidentReport -> accidentReport.getAccidentType().contains(item.getDictKey())).count();

                    //数量赋值
                    pieByLevel.setValue((int) count);

                    pieByTypeList.add(pieByLevel);
                });

                accidentStatisticsResp.setSource(pieByTypeList);
                break;
            //原因——饼图
            case ACCIDENT_REASON:
                //查询 事故类型 的数据字典
                SysDictType sysDictTypeByAccidentReason = sysDictTypeService.lambdaQuery().eq(SysDictType::getDictType, DicTypeCode.ACCIDENT_CAUSE.name()).eq(SysDictType::getStatus,"0").list().get(0);

                List<SysDictData> sysDictDataByAccidentReasonList = sysDictDataService.lambdaQuery().eq(SysDictData::getDictId, sysDictTypeByAccidentReason.getDictId()).eq(SysDictData::getStatus,"0").list();

                List<AccidentStatisticsResp.Pie> pieByReasonList = new ArrayList<>();

                //事故类型数据饼图结构赋值
                sysDictDataByAccidentReasonList.stream().forEach(item -> {
                    AccidentStatisticsResp.Pie pieByLevel = new AccidentStatisticsResp.Pie();
                    //相应
                    pieByLevel.setName(item.getDictKey());

                    //判断是否包含此类型id
                    long count = accidentReportList.stream().filter(accidentReport -> accidentReport.getAccidentCause().contains(item.getDictKey())).count();

                    //数量赋值
                    pieByLevel.setValue((int) count);

                    pieByReasonList.add(pieByLevel);
                });

                accidentStatisticsResp.setSource(pieByReasonList);
                break;
            default:
                throw new BusinessException("统计类型不存在，请联系管理员！");
        }
        return accidentStatisticsResp;
    }

    @Override
    public List<AccidentExport> export(AccidentReportExportReq accidentReportExportReq) throws Exception {

        if (StringUtils.isNotBlank(accidentReportExportReq.getIds())) {
            accidentReportExportReq.setIdList(Arrays.asList(accidentReportExportReq.getIds().split(",")));
        }
        //条件组合
        QueryWrapper<AccidentReport> queryWrapper = this.queryCondition(accidentReportExportReq);

        //添加id集合（判断id集合是否有值，如果无值则为全选）
        queryWrapper.in(CollectionUtils.isNotEmpty(accidentReportExportReq.getIdList()), AccidentReport.ID, accidentReportExportReq.getIdList());

        //根据条件查询集合
        List<AccidentReport> accidentReportList = this.list(queryWrapper);

        if (CollectionUtils.isEmpty(accidentReportList)) {
            throw new BusinessException("没有数据可导出！");
        }

        List<String> accidentIdList = accidentReportList.stream().map(AccidentReport::getId).collect(Collectors.toList());

        //根据上报信息查询事故受伤人员信息集合
        List<AccidentPersonnel> accidentPersonnelList = accidentPersonnelManager.lambdaQuery()
                .in(AccidentPersonnel::getRefId, accidentIdList).list();

        //数据处理
        List<AccidentExport> accidentExportList = new ArrayList<>();

        int serialNumber = 1;
        //响应数据处理
        for (AccidentReport accidentReport : accidentReportList) {
            List<AccidentPersonnel> newAccidentPersonnel = accidentPersonnelList.stream().filter(accidentPersonnel -> accidentReport.getId().equals(accidentPersonnel.getRefId())).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(newAccidentPersonnel)) {
                int finalSerialNumber = serialNumber;
                newAccidentPersonnel.stream().forEach(item -> {
                    AccidentExport accidentExport = this.buildAccidentExport(accidentReport, item, finalSerialNumber);
                    accidentExportList.add(accidentExport);
                });
            } else {
                AccidentExport accidentExport = this.buildAccidentExport(accidentReport, null, serialNumber);
                accidentExportList.add(accidentExport);
            }
            serialNumber++;
        }
        return accidentExportList;

    }

    private List<List<String>> getExcelHead() {
        List<List<String>> headers = new ArrayList<>();
        //序号
        List<String> baseSerialHead = new ArrayList<>();
        baseSerialHead.add("中粮贸易质量安全小事故信息统计表");
        baseSerialHead.add("序号");
        baseSerialHead.add("序号");

        //业务单位名称
        List<String> baseBusUnitHead = new ArrayList<>();
        baseBusUnitHead.add("中粮贸易质量安全小事故信息统计表");
        baseBusUnitHead.add("业务单位名称");
        baseBusUnitHead.add("业务单位名称");

        //基层企业名称
        List<String> baseBasicLevelHead = new ArrayList<>();
        baseBasicLevelHead.add("中粮贸易质量安全小事故信息统计表");
        baseBasicLevelHead.add("基层企业名称");
        baseBasicLevelHead.add("基层企业名称");

        //时间（年月日时）
        List<String> baseTimeYearHead = new ArrayList<>();
        baseTimeYearHead.add("中粮贸易质量安全小事故信息统计表");
        baseTimeYearHead.add("时间（年月日时）");
        baseTimeYearHead.add("年");

        //时间（年月日时）
        List<String> baseTimeMonthHead = new ArrayList<>();
        baseTimeMonthHead.add("中粮贸易质量安全小事故信息统计表");
        baseTimeMonthHead.add("时间（年月日时）");
        baseTimeMonthHead.add("月");

        //时间（年月日时）
        List<String> baseTimeDayHead = new ArrayList<>();
        baseTimeDayHead.add("中粮贸易质量安全小事故信息统计表");
        baseTimeDayHead.add("时间（年月日时）");
        baseTimeDayHead.add("日");

        //时间（年月日时）
        List<String> baseTimeHourHead = new ArrayList<>();
        baseTimeHourHead.add("中粮贸易质量安全小事故信息统计表");
        baseTimeHourHead.add("时间（年月日时）");
        baseTimeHourHead.add("时");

        return headers;
    }


    /**
     * @description: 组装导出数据
     * @param: [accidentReport, accidentPersonnel, serialNumber]
     * @return: com.testor.module.accident.model.excel.AccidentExport
     * @author zhangyangfan@testor.com.cn
     * @date: 2022/5/17 17:01
     */
    private AccidentExport buildAccidentExport(AccidentReport accidentReport, AccidentPersonnel accidentPersonnel, int serialNumber) {
        AccidentExport accidentExport = new AccidentExport();
        //序号
        accidentExport.setSerialNumber(serialNumber);

        //上报单位
        ReportUnitResp reportUnitResp = JSONObject.parseObject(accidentReport.getReportUnit(), ReportUnitResp.class);

        //业务单位名称
        if (ObjectHelper.isNotEmpty(reportUnitResp)) {
            accidentExport.setRegionalCompanyName(StringUtils.isNotBlank(reportUnitResp.getRegionalCompanyId()) ? reportUnitResp.getRegionalCompany() : "/");
        }

        //基层企业名称
        if (ObjectHelper.isNotEmpty(reportUnitResp)) {
            accidentExport.setBasicUnitName(StringUtils.isNotBlank(reportUnitResp.getBasicUnitId()) ? reportUnitResp.getBasicUnit() : "/");
        }

        //上报时间
        Calendar cal = Calendar.getInstance();
        cal.setTime(accidentReport.getAccidentTime());

        //上报时间——年
        accidentExport.setReportTimeYear(cal.get(Calendar.YEAR));

        //上报时间——月
        accidentExport.setReportTimeMonth(cal.get(Calendar.MONTH)+1);

        //上报时间——日
        accidentExport.setReportTimeDay(cal.get(Calendar.DATE));

        //上报时间——时
        accidentExport.setReportTimeHour(cal.get(Calendar.HOUR));

        //是否节假日
        accidentExport.setFakeTypeName(CacheDicUtils.get(DicTypeCode.FAKE_TYPE.name(), accidentReport.getFakeType()));

        //受伤人员信息
        if (Objects.nonNull(accidentPersonnel)) {
            //姓名
            accidentExport.setName(accidentPersonnel.getUserName());
            //年龄
            accidentExport.setAge(accidentPersonnel.getAge());
            //性别（0男1女）
            accidentExport.setGender(Boolean.getBoolean(accidentPersonnel.getSex()) ? "女" : "男");
            //归属类型
            accidentExport.setBelongTypeName(CacheDicUtils.get(DicTypeCode.BELONG_TYPE.name(), accidentPersonnel.getBelongType()));
        }

        //事故等级
        accidentExport.setAccidentLevelName(CacheDicUtils.get(DicTypeCode.ACCIDENT_LEVEL.name(), accidentReport.getAccidentLevel()));

        //事故类型
        accidentExport.setAccidentTypeName(CacheDicUtils.getByKeys(DicTypeCode.ACCIDENT_TYPE.name(), accidentReport.getAccidentType(), ","));

        //经济损失——合计（万元）
        accidentExport.setTotalEconomicLoss(accidentReport.getTotalEconomicLoss());

        //经济损失——直接(万元）
        accidentExport.setDirectEconomicLoss(accidentReport.getDirectEconomicLoss());

        //经济损失——间接（万元）
        accidentExport.setIndirectEconomicLoss(accidentReport.getIndirectEconomicLoss());

        //事故经过简述
        accidentExport.setAccidentPassed(accidentReport.getAccidentPassed());

        //事故原因
        accidentExport.setAccidentCause(accidentReport.getAccidentCause());

        //改善措施
        accidentExport.setImprovements(accidentReport.getImprovements());

        //备注
        accidentExport.setRemark(accidentReport.getRemarks());

        return accidentExport;
    }

    @Override
    public QueryWrapper<AccidentReport> queryCondition(AccidentReportQueryReq param) throws Exception {
        //权限控制
        ReportUnitResp reportUnit = this.getReportUnit();

        /*if (StringUtils.isNotEmpty(reportUnit.getBasicUnitId())) {
            param.setBasicUnitId(reportUnit.getBasicUnitId());
        }*/
        if (StringUtils.isNotEmpty(reportUnit.getOrgId())) {
            param.setOrgId(reportUnit.getBasicUnitId());
        }
        if (StringUtils.isNotEmpty(reportUnit.getRegionalCompanyId())) {
            param.setRegionalCompanyId(reportUnit.getRegionalCompanyId());
        }
        /*if(StringUtils.isNotEmpty(reportUnit.getThirdLevelUnitId())){
            param.setThirdLevelUnitId(reportUnit.getThirdLevelUnitId());
        }*/
        QueryWrapper<AccidentReport> queryWrapper = this.createQuery(param);

        //只能看到审核通过的数据
        queryWrapper.eq(AccidentReport.PROCESS_STATUS, ProcessStatus.PASSED.getCode());
        return queryWrapper;
    }

    @Override
    public AccidentReportExportReq queryConditions(AccidentReportExportReq param) throws Exception {
        //权限控制
        ReportUnitResp reportUnit = this.getReportUnit();

        if (StringUtils.isNotEmpty(reportUnit.getBasicUnitId())) {
            param.setBasicUnitId(reportUnit.getBasicUnitId());
        }
        if (StringUtils.isNotEmpty(reportUnit.getRegionalCompanyId())) {
            param.setRegionalCompanyId(reportUnit.getRegionalCompanyId());
        }
//        QueryWrapper<AccidentReport> queryWrapper = this.createQuery(param);

        //只能看到审核通过的数据
        /*if (!StringHelper.isNotEmpty(reportUnit.getBasicUnitId())) {
            param.setProcessStatus("5");
        }*/
        param.setProcessStatus(ProcessStatus.PASSED.getCode());
        String rule = sysRuleService.dataRuleScope(DefaultRule.DEPT_SUB.name());
        if (StringUtils.isNotEmpty(rule)) {
            param.setOrgSql(rule);
        }
        return param;
    }

    @Override
    public void physicsDelete(String id) throws Exception {
        AccidentReport accidentReport = this.getById(id);

        if (!ProcessStatus.SUBMIT.getCode().equals(accidentReport.getProcessStatus())) {
            throw new BusinessException("只有提交状态下才能删除事故上报！");
        }

        //删除事故受伤人员信息
        accidentPersonnelManager.deleteByRefId(id);

        //删除事故上报
        accidentReportDao.deleteById(id);
    }

    @Override
    public String getCountByAccidentTime(Integer accidentTime , String orgId) {
        if (StringHelper.isEmpty(orgId)) {
            orgId = ContextUtils.getLoginUser().getOrgId();
        }
        AccidentReport accidentReport = new AccidentReport();
        accidentReport.setAttachment(Integer.toString(accidentTime));
        accidentReport.setOrgId(orgId);
        return accidentReportDao.getCountByAccidentTime(accidentReport);
    }

    @Override
    public List<AccidentReport> getAccidentReportByAccidentTime(Integer accidentTime, String orgId) {
        if (StringHelper.isEmpty(orgId)) {
            orgId = ContextUtils.getLoginUser().getOrgId();
        }
        AccidentReport accidentReport = new AccidentReport();
        accidentReport.setAttachment(Integer.toString(accidentTime));
        accidentReport.setOrgId(orgId);
       return accidentReportDao.getAccidentReportByAccidentTime(accidentReport);
    }

    @Override
    public void exports(HttpServletResponse response, HttpServletRequest request, AccidentReportExportReq accidentReportExportReq) {
        if (StringUtils.isNotBlank(accidentReportExportReq.getIds())) {
            accidentReportExportReq.setIdList(Arrays.asList(accidentReportExportReq.getIds().split(",")));
        }
        //条件组合
//        QueryWrapper<AccidentReport> queryWrapper = null;
        AccidentReportExportReq accidentReportQueryReq=null;
        try {
//            queryWrapper = this.queryCondition(accidentReportExportReq);
             accidentReportQueryReq = this.queryConditions(accidentReportExportReq);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //添加id集合（判断id集合是否有值，如果无值则为全选）
//        queryWrapper.in(CollectionUtils.isNotEmpty(accidentReportExportReq.getIdList()) && accidentReportExportReq.getIdList().size()>0, AccidentReport.ID, accidentReportExportReq.getIdList());

        //根据条件查询集合
        if (accidentReportExportReq.getIdList().size()==0) {
            accidentReportExportReq.setIdList(null);
        }
        List<AccidentReport> accidentReportList = accidentReportDao.findExportlist(accidentReportQueryReq);

//        List<AccidentReport> accidentReportList = this.list(queryWrapper);
        List<AccidentExportVO> accidentExports=new ArrayList<>();
        List<AccidentExportVO>list=new ArrayList<>();
        if (CollectionUtils.isNotEmpty(accidentReportList)) {
            //查询事故受伤人员信息
            List<String> collect = accidentReportList.stream().map(AccidentReport::getId).collect(Collectors.toList());
            List<AccidentPersonnel> accidentPersonnelLists = accidentPersonnelManager
                    .list(new QueryWrapper<AccidentPersonnel>().select("ref_id","belong_type","belong_unit","user_name","age","sex").in("ref_id", collect));

            List<AccidentPersonnelVO> accidentPersonnelVOList=new ArrayList<>();
            if (CollectionUtils.isNotEmpty(accidentPersonnelLists)) {
                 accidentPersonnelVOList = accidentPersonnelLists.stream().map(item -> {
                    AccidentPersonnelVO accidentPersonnelVO = BeanHelper.beanToBean(item, AccidentPersonnelVO.class);
                    //中文转换
                    accidentPersonnelVO.setSexName(EnumUtil.getByCode(accidentPersonnelVO.getSex(), SexEnum.class));
                    accidentPersonnelVO.setBelongTypeName(EnumUtil.getByCode(accidentPersonnelVO.getBelongType(), BelongUnitEnum.class));
                    return accidentPersonnelVO;
                }).collect(Collectors.toList());
            }

            //todo 填充事故信息
             accidentExports = Beans.listToBean(accidentReportList, AccidentExportVO.class);
            List<AccidentPersonnelVO> finalAccidentPersonnelVOList = accidentPersonnelVOList;


            List<AccidentExportVO> finalAccidentExports = accidentExports;
            List<AccidentExportVO> finalAccidentExport = new ArrayList<>();
            accidentExports.forEach(a->{
                finalAccidentPersonnelVOList.forEach(f->{
                    if (a.getId().equals(f.getRefId())) {
                        com.testor.module.accident.model.excel.AccidentPersonnelVO accidentPersonnelVO =
                                Beans.objectToBean(f, com.testor.module.accident.model.excel.AccidentPersonnelVO.class);
                        a.setName(accidentPersonnelVO.getUserName());
                        a.setBelongTypeName(accidentPersonnelVO.getBelongTypeName());
                        a.setAge(accidentPersonnelVO.getAge());
                        a.setGender(accidentPersonnelVO.getSexName());
                        list.add(a);
                        finalAccidentExport.add(a);
                    }
                });
            });
            for (int i = 0; i < finalAccidentExport.size(); i++) {
                finalAccidentExports.remove(finalAccidentExport.get(i));

            }
            list.addAll(finalAccidentExports);
            list.forEach(c->{
                 accidentReportList.forEach(a->{
                     if (c.getId().equals(a.getId())) {
                         ReportUnitResp reportUnitResp = JSONObject.parseObject(a.getReportUnit(), ReportUnitResp.class);
                         c.setBasicUnitName(StringUtils.isNotBlank(a.getBasicUnitId()) ? reportUnitResp.getBasicUnit() : "/");
                         c.setRegionalCompanyName(StringUtils.isNotBlank(a.getRegionalCompanyId()) ? reportUnitResp.getRegionalCompany() : "/");
                         c.setDeptName(reportUnitResp.getPath());
                         c.setAccidentTypeName(CacheDicUtils.getByKeys(DicTypeCode.ACCIDENT_TYPE.name(), a.getAccidentType(), ","));
                         c.setAccidentLevelName(CacheDicUtils.get(DicTypeCode.ACCIDENT_LEVEL.name(), a.getAccidentLevel()));
                         c.setAccidentCause(CacheDicUtils.getByKeys(DicTypeCode.ACCIDENT_CAUSE.name(), a.getAccidentCause(),","));
                         if (a.getAccidentTime()!= null) {
                             //ToDo  获取年月日时
                             Date accidentTime = a.getAccidentTime();
                             Calendar ca = Calendar.getInstance();
                             ca.setTime(accidentTime);
                             c.setReportTimeYear(ca.get(Calendar.YEAR));
                             c.setReportTimeMonth(ca.get(Calendar.MONTH)+1);
                             c.setReportTimeDay(ca.get(Calendar.DAY_OF_MONTH));
                             c.setReportTimeHour(ca.get(Calendar.HOUR_OF_DAY));
                         }
                         c.setFakeTypeName(EnumUtil.getByCode(a.getFakeType(), FakeType.class));
                     }
                 });
             });

        }
        if (CollectionUtils.isNotEmpty(list)) {
            int index=1;
            for (int i = 0; i < list.size(); i++) {
                list.get(i).setSerialNumber(index);
                index++;
            }
        }

        try (OutputStream out = response.getOutputStream()) {
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            String fileName = URLEncoder.encode(AccidentExport.EXCEL_FILE_NAME, "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
            WriteSheet dealerSheet = EasyExcel.writerSheet(0, "事故上报信息")
                    .registerWriteHandler(new AutoHeadColumnWidthStyleStrategy()).head(AccidentExportVO.class).build();
            ExcelWriter build = EasyExcelFactory.write(out).build();
            build.write(list,dealerSheet);
            build.finish();
            out.flush();
        } catch (Exception e) {
            log.error(e.getMessage());
        }

    }

    @Override
    public Page<AccidentReportDetail> selectAccidentReportDetail(ReportDetailParam param) {
        Long page =
                StringHelper.isEmpty(param.getPage()) ? BizConstants.PAGE : Long.valueOf(param.getPage());
        Long limit =
                StringHelper.isEmpty(param.getLimit()) ? BizConstants.LIMIT : Long.valueOf(param.getLimit());
        Page<THazardWorkPlan> resultPage = new Page<>(page, limit);

        if(StringUtils.isEmpty(param.getOrgId())){
            SysUser user = sysUserService.getById(param.getUserId());
            if(user != null){
                param.setOrgId(user.getOrgId());
            }
        }
        Page<AccidentReportDetail> accidentReportDetailPage = accidentReportDao.selectAccidentReportDetail(resultPage, param);

        accidentReportDetailPage.getRecords().forEach(c->{
            if(c.getReportCount()>0){
                c.setAccidentPersonnelList(accidentPersonnelManager.list(new QueryWrapper<AccidentPersonnel>().eq(AccidentPersonnel.REF_ID, c.getId())));
            }
        });

        return accidentReportDetailPage;
    }

    /**
     * 列表查询条件及查询参数
     */
    private QueryWrapper<AccidentReport> createQuery(AccidentReportQueryReq queryParam) {
        QueryWrapper<AccidentReport> queryWrapper = new QueryWrapper<>();

        // Data Rule
//        if (StringUtils.isNotEmpty(queryParam.getDataRuleCode())) {
        String rule = sysRuleService.dataRuleScope(DefaultRule.DEPT_SUB.name());
        if (StringUtils.isNotEmpty(rule)) {
            queryWrapper.apply(rule);
        }
//        }
        if(StringUtils.isNotBlank(queryParam.getDeptId())){
            queryWrapper.eq(AccidentReport.ORG_ID, queryParam.getDeptId());
        }
        if (org.apache.commons.lang.StringUtils.isNotBlank(queryParam.getRegionalCompanyId())) {
            queryWrapper.eq(AccidentReport.REGIONAL_COMPANY_ID, queryParam.getRegionalCompanyId());
        }
        if (org.apache.commons.lang.StringUtils.isNotBlank(queryParam.getBasicUnitId()) || org.apache.commons.lang.StringUtils.isNotBlank(queryParam.getOrgId())) {
            queryWrapper.or().eq(AccidentReport.BASIC_UNIT_ID, queryParam.getBasicUnitId()).or().eq(AccidentReport.ORG_ID, queryParam.getOrgId());
        }
        if (org.apache.commons.lang.StringUtils.isNotBlank(queryParam.getProcessStatus())) {
            queryWrapper.eq(AccidentReport.PROCESS_STATUS, queryParam.getProcessStatus());
        }
        if (org.apache.commons.lang.StringUtils.isNotBlank(queryParam.getAccidentLevel())) {
            queryWrapper.eq(AccidentReport.ACCIDENT_LEVEL, queryParam.getAccidentLevel());
        }
        if (ObjectHelper.isNotEmpty(queryParam.getAccidentStartTime())) {
            queryWrapper.ge(AccidentReport.ACCIDENT_TIME, queryParam.getAccidentStartTime());
        }
        if (ObjectHelper.isNotEmpty(queryParam.getAccidentEndTime())) {
            queryWrapper.le(AccidentReport.ACCIDENT_TIME, queryParam.getAccidentEndTime());
        }
        /*if(ObjectHelper.isNotEmpty(queryParam.getThirdLevelUnitId())){
            queryWrapper.eq(AccidentReport.THIRD_LEVEL_UNIT_ID, queryParam.getThirdLevelUnitId());
        }*/
        if (org.apache.commons.lang.StringUtils.isNotBlank(queryParam.getOrderBy())) {
            if (StringHelper.isNotEmpty(queryParam.getOrderType()) && BizConstants.ASC.equals(queryParam.getOrderType())) {
                queryWrapper.orderByAsc(queryParam.getOrderBy());
            } else {
                queryWrapper.orderByDesc(queryParam.getOrderBy());
            }
        } else {
            queryWrapper.orderByDesc(AccidentReport.UPDATE_DATE);
        }
        return queryWrapper;
    }


}

