package com.docus.server.ydzyy.job;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.docus.core.util.Func;
import com.docus.infrastructure.redis.service.IdService;
import com.docus.server.archive.entity.AfCollectTask;
import com.docus.server.archive.entity.TBasic;
import com.docus.server.archive.mapper.TBasicMapper;
import com.docus.server.rpc.DownPlatformService;
import com.docus.server.rpc.YdZyyPacsService;
import com.docus.server.rpc.dto.ReportDownDto;
import com.docus.server.rpc.dto.ReportDownPatientDto;
import com.docus.server.rpc.dto.ReportDownScanFileDto;
import com.docus.server.util.TableJsonRead;
import com.docus.server.ydzyy.dto.YdZyyPacsViewCondition;
import com.docus.server.ydzyy.entity.YdZyyPacsView;
import com.docus.server.ydzyy.mapper.YdZyyPacsViewMapper;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * pacs系统采集任务
 *
 * @author YongBin Wen
 * @date 2024/9/4 11:27
 */
@Component
@Slf4j
public class PacsCollectJob {
    @Resource
    private TBasicMapper tBasicMapper;

    @Resource
    private YdZyyPacsViewMapper ydZyyPacsViewMapper;

    @Resource
    private DownPlatformService downPlatformService;

    @Resource
    private IdService idService;

    @Resource
    private YdZyyPacsService ydZyyPacsService;


    @XxlJob("Ydzyy-CollectPacsByDisDateNotCollected")
    public void collectPacsByDisDateNotCollected() {
        String collectorId = "3";
        log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>英德中医院pacs视图采集,根据出院时间和未采集job，开始任务！");
        int days;
        try {
            String daysStr = XxlJobHelper.getJobParam();
            days = Integer.parseInt(daysStr);
        } catch (Exception ex) {
            days = 31;
        }
        LocalDate startDate = LocalDate.now().plusDays(-days);
        String startDateTime = startDate.toString() + " 00:00:00";

        try {
            List<TBasic> basicList = tBasicMapper.getNoTaskPatientByDisDate(startDateTime, collectorId);
            log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>英德中医院pacs视图采集,根据出院时间：{} 采集未采集的患者，{} 个", startDateTime, basicList.size());
            for (TBasic basic : basicList) {
                collectPacs(basic,false);
            }
            log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>英德中医院pacs视图采集,根据出院时间和未采集job，任务结束！");
        } catch (Exception ex) {
            log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>英德中医院pacs视图采集,根据出院时间和未采集job，任务异常！" + ex.getMessage(), ex);
        }
    }

    @XxlJob("Ydzyy-CollectPacsByModifyTime")
    public void collectPacsByModifyTime() {
        LocalDateTime jobRunTime = LocalDateTime.now();
        // 查询视图 ,根据视图信息查询患者，再根据患者同步 所有的任务、文件
        log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>英德中医院pacs视图采集job，开始任务！");
        try {
            String configPath = "data-config";
            String configName = "ydzyy-pacs-collect-job";
            TableJsonRead tableJsonRead = new TableJsonRead();
            JSONObject jobConfig = tableJsonRead.Read(configPath, configName, JSONObject.class);
            String startTime = jobConfig.getString("startTime");
            int deviationSeconds = jobConfig.getIntValue("deviationSeconds");
            if (Func.isBlank(startTime)) {
                log.error(">>>>>>>>>>>>>>>>>>>>>>>>>>>英德中医院pacs视图采集job，配置开始时间为空！");
                return;
            }
            YdZyyPacsViewCondition pacsViewCondition = new YdZyyPacsViewCondition();
            pacsViewCondition.setChangeTimeStart(startTime);
            String conditionJsonStr = JSON.toJSONString(pacsViewCondition);
            List<YdZyyPacsView> ydZyyPacsViews = ydZyyPacsViewMapper.pacsViews(pacsViewCondition);
            if (Func.isEmpty(ydZyyPacsViews)) {
                log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>英德中医院pacs视图采集job，参数：{} ,未查询到数据，结束任务！", conditionJsonStr);
            }
            log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>英德中医院pacs视图采集job，参数：{} ,查询到数据 {} 条", conditionJsonStr, ydZyyPacsViews.size());
            List<TBasic> tBasicList = new ArrayList<>();
            Set<String> patientIdSet = new HashSet<>();
            for (YdZyyPacsView ydZyyPacsView : ydZyyPacsViews) {
                String idCard = ydZyyPacsView.getIDCARD();
                String inpatientNo = ydZyyPacsView.getNP_NO();
                if (Func.isBlank(idCard) && Func.isBlank(inpatientNo)) {
                    continue;
                }
                Date sendDate = ydZyyPacsView.getSENDDATE();
                if (Func.isEmpty(sendDate)) {
                    continue;
                }
                String sendDateStr = Func.formatDateTime(sendDate);

                List<TBasic> tBasicListByPacsCondition = tBasicMapper.getTbasicByReportTimeAndInpNoOrIdCard(sendDateStr, Func.isBlank(idCard) ? inpatientNo : idCard, Func.isBlank(inpatientNo) ? idCard : inpatientNo);
                if (Func.isEmpty(tBasicListByPacsCondition)) {
                    log.warn(">>>>>>>>>>>>>>>>>>>>>>>>>>>英德中医院pacs视图采集job，pacs视图数据，未匹配到患者基础数据，请检查！数据：{}", JSON.toJSONString(ydZyyPacsView));
                    continue;
                }
                // 如果有住院号，住院号一定要匹配,并且根据住院日期倒序取第一个（最大的出院日期）
                tBasicListByPacsCondition = tBasicListByPacsCondition.stream()
                        .filter(p -> {
                            if (Func.isNotBlank(inpatientNo)) {
                                return inpatientNo.equalsIgnoreCase(p.getInpatientNo());
                            }
                            return true;
                        })
                        .collect(Collectors.toList());
                if (Func.isEmpty(tBasicListByPacsCondition)) {
                    log.warn(">>>>>>>>>>>>>>>>>>>>>>>>>>>英德中医院pacs视图采集job，pacs视图数据，未匹配到患者基础数据，请检查！数据：{}", JSON.toJSONString(ydZyyPacsView));
                    continue;
                }

                if (tBasicListByPacsCondition.size() > 1) {
                    log.warn(">>>>>>>>>>>>>>>>>>>>>>>>>>>英德中医院pacs视图采集job，pacs视图数据，匹配到多个患者基础数据，请检查！数据：{}", JSON.toJSONString(ydZyyPacsView));
                    tBasicListByPacsCondition = tBasicListByPacsCondition.stream()
                            .sorted(Comparator.comparing(TBasic::getAdmissDate).reversed())
                            .collect(Collectors.toList());
                }
                TBasic basic = tBasicListByPacsCondition.get(0);
                String patientId = basic.getPatientId();
                if (patientIdSet.contains(patientId)) {
                    continue;
                }
                patientIdSet.add(patientId);
                tBasicList.add(basic);
            }
            for (TBasic basic : tBasicList) {
                collectViewPacs(basic);
            }
            LocalDateTime nextStartTime = jobRunTime.plusSeconds(-deviationSeconds);
            jobConfig.put("startTime", Func.formatDateTime(nextStartTime));
            tableJsonRead.Save(configPath, configName, jobConfig.toJSONString());
        } catch (Exception ex) {
            log.error(">>>>>>>>>>>>>>>>>>>>>>>>>>>英德中医院pacs视图采集jobc出现异常，结束任务！" + ex.getMessage(), ex);
        }

        log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>英德中医院pacs视图采集job，结束任务！");
    }

    @XxlJob("Ydzyy-CollectPacsByFailedTask")
    public void collectPacsByFailedTask() {
        String collectorId = "3";
        String assortId = "AC2C8F4A88884DC894630302C61C6A07";
        List<String> notReCollectState = Arrays.asList("3", "4");
        log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>英德中医院pacs任务补偿job，开始任务！");
        try {
            LocalDate startDate = LocalDate.now().plusMonths(-3);
            String startDateStr = startDate + " 00:00:00";
            List<String> patientIds = tBasicMapper.findFailedTaskPatId(collectorId, startDateStr);
            log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>英德中医院pacs任务补偿job,查询创建时间>={} 失败的任务患者数量：{} 个。", startDateStr, patientIds);
            if (Func.isEmpty(patientIds)) {
                return;
            }
            // 失败重采不从视图，从接口获取
//            List<TBasic> tBasicList = tBasicMapper.getTbasicByPatientIds(patientIds);
//            for (TBasic tBasic : tBasicList) {
//                collectPacs(tBasic);
//            }
            for (String patientId : patientIds) {
                ReportDownPatientDto patient = new ReportDownPatientDto();
                patient.setPatientid(patientId);
                ReportDownDto reportDownDto = new ReportDownDto();
                reportDownDto.setAssortid(assortId);
                reportDownDto.setCollectorid(collectorId);
                reportDownDto.setIp("java-collect-pacs");
                reportDownDto.setPatient(patient);
                List<AfCollectTask> tasks = tBasicMapper.getCollectTaskByPatAndSource(patientId, collectorId);
                List<AfCollectTask> reCollectTask = tasks.stream().filter(task -> !notReCollectState.contains(task.getState())).collect(Collectors.toList());
                for (AfCollectTask task : reCollectTask) {
                    String remark = task.getC1();
                    YdZyyPacsViewCondition viewCondition = new YdZyyPacsViewCondition();
                    viewCondition.setRemark(remark);
                    List<YdZyyPacsView> pacsViews = ydZyyPacsViewMapper.longTimePacsViews(viewCondition);
                    if (Func.isEmpty(pacsViews)) {
                        tBasicMapper.delTaskById(task.getId());
                        tBasicMapper.flushPatTaskEndTime(patientId, Func.formatDateTime(new Date()));
                        log.warn("remark:{} ,patientId:{} 视图已经不存在pacs报告信息,删除任务！", remark, patientId);
                        continue;
                    }

                    String base64 = ydZyyPacsService.getJpgReportBase64(remark);
                    if (Func.isBlank(base64)) {
                        log.info("remark:{} 获取pacs图片报告base64失败！", remark);
                        continue;
                    }
                    ReportDownScanFileDto reportDownScanFileDto = new ReportDownScanFileDto();
                    reportDownScanFileDto.setDownurl(base64);
                    reportDownScanFileDto.setFiletitle(task.getC6());
                    reportDownScanFileDto.setSerialnum(remark);
                    reportDownScanFileDto.setFilesource(1);
                    reportDownScanFileDto.setFiletype(2);
                    reportDownScanFileDto.setFilestoragetype(1);
                    reportDownScanFileDto.setTaskid(task.getId());
                    List<ReportDownScanFileDto> scanFiles = Collections.singletonList(reportDownScanFileDto);
                    reportDownDto.setScanfiles(scanFiles);
                    downPlatformService.report(reportDownDto);

                }
            }

        } catch (Exception ex) {
            log.error(">>>>>>>>>>>>>>>>>>>>>>>>>>>英德中医院pacs任务补偿job出现异常，结束任务！" + ex.getMessage(), ex);
        }

        log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>英德中医院pacs任务补偿job，结束任务！");
    }

    public static void main(String[] args) {
        System.out.println(Func.formatDateTime(new Date()).substring(0, 10));
    }

    private void collectViewPacs(TBasic basic) {
        collectPacs(basic, true);
    }


    public void collectPacs(TBasic basic, boolean isView) {
        String collectorId = "3";
        String assortId = "AC2C8F4A88884DC894630302C61C6A07";
        String patientId = basic.getPatientId();
        // 获取视图数据
        List<YdZyyPacsView> finalPacsViews = isView ? getPacsViews(basic) : getPacs(basic, isView);
        if (Func.isEmpty(finalPacsViews)) {
            tBasicMapper.invalidFileBySource(patientId, collectorId);
            tBasicMapper.deleteTaskByPatAndSource(patientId, collectorId);
            // 刷新结束时间只是因为要校验完整性
            tBasicMapper.flushPatTaskEndTime(patientId, Func.formatDateTime(new Date()));
            return;
        }

        // 处理采集任务
        Map<String, YdZyyPacsView> pacsViewMap = finalPacsViews.stream().collect(Collectors.toMap(YdZyyPacsView::getREMARK, Function.identity()));
        Set<String> reamarks = pacsViewMap.keySet();
        List<AfCollectTask> collectTaskList = tBasicMapper.getCollectTaskByPatAndSource(patientId, collectorId);
        List<String> taskC1s = collectTaskList.stream().map(AfCollectTask::getC1).collect(Collectors.toList());
        List<AfCollectTask> delTaskList = collectTaskList.stream()
                .filter(task -> !reamarks.contains(task.getC1()))
                .collect(Collectors.toList());
        List<AfCollectTask> updateTaskList = collectTaskList.stream()
                .filter(task -> reamarks.contains(task.getC1()))
                .collect(Collectors.toList());

        List<AfCollectTask> addTaskList = new ArrayList<>();
        for (YdZyyPacsView pacsView : finalPacsViews) {
            if (taskC1s.contains(pacsView.getREMARK())) {
                continue;
            }
            AfCollectTask task = new AfCollectTask();
            task.setId(idService.getDateSeq());
            task.setAfArchiveDetailId(0L);
            task.setPatientId(patientId);
            task.setSysflag(collectorId);
            task.setSyncTime(new Date());
            task.setCreateTime(new Date());
            task.setState("0");
            task.setC1(pacsView.getREMARK());
            task.setC2(pacsView.getREGISTER_NUM());
            task.setC3(pacsView.getNP_NO());
            task.setC4(pacsView.getACCNO());
            task.setC5(basic.getJzh());
            task.setC6(pacsView.getREPORTNAME());
            task.setC7(pacsView.getNAME());
            task.setT1(Func.parseDate(pacsView.getCREATETIMESTR(), "yyyy-MM-dd"));
            task.setT2(pacsView.getADUITTIME());
            task.setT3(pacsView.getSTATUSCHGTIME());
            addTaskList.add(task);
            pacsView.setTaskId(task.getId());
        }

        if (Func.isNotEmpty(delTaskList)) {
            for (AfCollectTask task : delTaskList) {
                tBasicMapper.delTaskById(task.getId());
            }
        }
        if (Func.isNotEmpty(updateTaskList)) {
            for (AfCollectTask task : updateTaskList) {
                YdZyyPacsView pacsView = pacsViewMap.get(task.getC1());
                pacsView.setTaskId(task.getId());
                task.setSyncTime(new Date());
                task.setC2(pacsView.getREGISTER_NUM());
                task.setC3(pacsView.getNP_NO());
                task.setC4(pacsView.getACCNO());
                task.setC5(basic.getJzh());
                task.setC6(pacsView.getREPORTNAME());
                task.setC7(pacsView.getNAME());
                task.setT1(Func.parseDate(pacsView.getCREATETIMESTR(), "yyyy-MM-dd"));
                task.setT2(pacsView.getADUITTIME());
                task.setT3(pacsView.getSTATUSCHGTIME());
                tBasicMapper.updateTaskById(task);
            }
        }
        if (Func.isNotEmpty(addTaskList)) {
            for (AfCollectTask task : addTaskList) {
                tBasicMapper.insertCollectTask(task);
            }
        }
        tBasicMapper.invalidFileBySource(patientId, collectorId);
        // 上报文件
        ReportDownPatientDto patient = new ReportDownPatientDto();
        patient.setPatientid(patientId);
        ReportDownDto reportDownDto = new ReportDownDto();
        reportDownDto.setAssortid(assortId);
        reportDownDto.setCollectorid(collectorId);
        reportDownDto.setIp("java-collect-pacs");
        reportDownDto.setPatient(patient);
        for (YdZyyPacsView pacsView : finalPacsViews) {
            ReportDownScanFileDto reportDownScanFileDto = new ReportDownScanFileDto();
            reportDownScanFileDto.setDownurl(pacsView.getFILEPATH());
            reportDownScanFileDto.setFiletitle(pacsView.getREPORTNAME());
            reportDownScanFileDto.setSerialnum(pacsView.getREMARK());
            reportDownScanFileDto.setFilesource(1);
            reportDownScanFileDto.setFiletype(4);
            reportDownScanFileDto.setFilestoragetype(1);
            reportDownScanFileDto.setTaskid(pacsView.getTaskId());
            List<ReportDownScanFileDto> scanFiles = Collections.singletonList(reportDownScanFileDto);
            reportDownDto.setScanfiles(scanFiles);
            downPlatformService.report(reportDownDto);
        }
    }


    /**
     * 根据患者获取pacs视图信息
     *
     * @param basic 患者信息
     */
    private List<YdZyyPacsView> getPacsViews(TBasic basic) {
        return getPacs(basic, true);
    }

    /**
     * 根据患者获取pacs视图信息
     *
     * @param basic 患者信息
     */
    private List<YdZyyPacsView> getPacs(TBasic basic, boolean isView) {
        String inpatientNo = basic.getInpatientNo();
        String idCard = basic.getIdCard();
        Date admissDate = basic.getAdmissDate();
        Date disDate = basic.getDisDate();
        String admissDateStr = Func.formatDateTime(admissDate).substring(0, 10);
        String disDateStr = disDate == null ? null : Func.formatDateTime(disDate);

        YdZyyPacsViewCondition pacsViewCondition = new YdZyyPacsViewCondition();
        pacsViewCondition.setInpNo(inpatientNo);
        pacsViewCondition.setSendDateStart(admissDateStr);
        pacsViewCondition.setSendDateEnd(disDateStr);
        // 住院pacs
        List<YdZyyPacsView> zyPacsViews = isView ? ydZyyPacsViewMapper.pacsViews(pacsViewCondition) : ydZyyPacsViewMapper.longTimePacsViews(pacsViewCondition);
        List<YdZyyPacsView> allPacsViews = new ArrayList<>(zyPacsViews);
        if (Func.isNotBlank(idCard)) {
            pacsViewCondition.setInpNo(null);
            pacsViewCondition.setIdCard(idCard);
            // 根据患者身份证查
            List<YdZyyPacsView> pacsViewsByIdCard = isView ? ydZyyPacsViewMapper.pacsViews(pacsViewCondition) : ydZyyPacsViewMapper.longTimePacsViews(pacsViewCondition);
            allPacsViews.addAll(pacsViewsByIdCard);
        }

        List<YdZyyPacsView> finalPacsViews = new ArrayList<>();
        Set<String> reamarks = new HashSet<>();
        for (YdZyyPacsView pacsView : allPacsViews) {
            if (reamarks.contains(pacsView.getREMARK())) {
                continue;
            }
            reamarks.add(pacsView.getREMARK());
            finalPacsViews.add(pacsView);
        }
        // 排序
        finalPacsViews = finalPacsViews.stream()
                .sorted(Comparator.comparing(YdZyyPacsView::getCREATETIMESTR))
                .collect(Collectors.toList());
        return finalPacsViews;
    }


}
