package com.docus.server.mzzyy.job;

import cn.hutool.core.io.FileUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.docus.core.util.Func;
import com.docus.infrastructure.core.exception.BaseException;
import com.docus.infrastructure.web.api.CommonResult;
import com.docus.infrastructure.web.api.ResultCode;
import com.docus.server.archive.dto.PatientState;
import com.docus.server.archive.entity.TBasic;
import com.docus.server.archive.mapper.TBasicMapper;
import com.docus.server.mzzyy.entity.MzZyyXinDianView;
import com.docus.server.mzzyy.mapper.MzZyyXinDianViewMapper;
import com.docus.server.rpc.DownPlatformService;
import com.docus.server.rpc.MzZyyLisService;
import com.docus.server.rpc.MzZyyShouMaService;
import com.docus.server.rpc.TaskDistributeService;
import com.docus.server.rpc.dto.MzZyyLisExportDto;
import com.docus.server.rpc.dto.MzZyyShouMaMedicalDocumentFileForBase64Dto;
import com.docus.server.rpc.dto.MzZyyShouMaMedicalDocumentInfoDto;
import com.docus.server.rpc.dto.MzZyyShouMaQueryMedicalDocumentInfoDto;
import com.docus.server.rpc.dto.MzZyyTestDto;
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.rpc.dto.ReportDownTwoDto;
import com.docus.server.rpc.dto.ReportHospitalTwoDto;
import com.docus.server.rpc.dto.ReportPatientTwoDto;
import com.docus.server.rpc.dto.ReportTaskTwoDto;
import com.docus.server.rpc.enums.MzZyyLisType;
import com.docus.server.util.StaticResourceMapping;
import com.docus.server.util.TableJsonRead;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.File;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;

/**
 * @author YongBin Wen
 * @date 2025/3/18 9:18
 */
@Component
@Slf4j
public class MzZyyReportCollectJob {
    @Autowired
    private DownPlatformService downPlatformService;
    @Autowired
    private TaskDistributeService taskDistributeService;
    @Autowired
    private MzZyyLisService mzZyyLisService;
    @Autowired
    private MzZyyShouMaService mzZyyShouMaService;
    @Autowired
    private TBasicMapper tBasicMapper;
    @Autowired
    private MzZyyXinDianViewMapper xinDianViewMapper;
    @Value("${docus.prevent-invalid-file:}")
    private String preventInvalidFile;

    @XxlJob("MzZyyLisCollectJob")
    public void lisCollectJob() {
        String configPath = "data-config";
        String configName = "mzzyy-ws-config";
        TableJsonRead jsonReader = new TableJsonRead();
        JSONObject configOjb = jsonReader.Read(configPath, configName, JSONObject.class);
        JSONObject lisWsConfig = configOjb.getJSONObject("lis");
        String collectorId = lisWsConfig.getString("collectorId");
        String assortId = lisWsConfig.getString("assortId");

        CommonResult<ReportDownTwoDto> commonResult = taskDistributeService.getNoViewTaskByCollectorId(collectorId);
        if (!ResultCode.SUCCESS.getCode().equals(commonResult.getCode())
                || commonResult.getData() == null) {
            return;
        }


        ReportDownTwoDto downTwoDto = commonResult.getData();
        ReportTaskTwoDto task = downTwoDto.getTasks().get(0);
        log.info(">>>>>>>>>>>>>>>>>>>>>> 梅州中医院Lis采集任务，获取了任务：{}", Func.toJson(task));

        ReportHospitalTwoDto hospitalTwoDto = downTwoDto.getHospitals().get(0);
        ReportPatientTwoDto reportPatientTwoDto = downTwoDto.getPatient();
        String jzh = downTwoDto.getJzh();
        String patientId = downTwoDto.getPatientId();
        String inpatientNo = reportPatientTwoDto.getInpatientNo();
        String patientType = "住院";
        List<MzZyyTestDto> testFormPdfs = mzZyyLisService.getTestFormPdf(jzh, inpatientNo, patientType);
        if (Func.isEmpty(testFormPdfs)) {
            determineAndCancelTask(patientId, collectorId);
            return;
        }
        String formatDate = Func.formatDate(new Date());
        String fileDirPath = TableJsonRead.currentPath(StaticResourceMapping.STATIC_RESOURCE_PREFIX + File.separator + StaticResourceMapping.LIS)
                + File.separator + formatDate
                + File.separator + patientId;
        List<String> fileKeys = new ArrayList<>();
        Map<String, List<String>> httpUrlsMap = new HashMap<>();
        Map<String, MzZyyTestDto> testFormPdfsMap = new HashMap<>();
        int i = 1;
        int count = 0;
        for (MzZyyTestDto testFormPdf : testFormPdfs) {
            ArrayList<String> urls = new ArrayList<>();
            try {
                MzZyyLisType lisType = MzZyyLisType.getLisType(testFormPdf.getType());
                List<MzZyyLisExportDto> base64Files = mzZyyLisService.exportTestFormPdf(lisType, testFormPdf.getMachineId(), testFormPdf.getSampleId(), testFormPdf.getTestDate());
                for (MzZyyLisExportDto base64File : base64Files) {
                    String filePath = fileDirPath + File.separator + i + "." + base64File.getType().toLowerCase(Locale.ROOT);
                    String httpUrl = "http://127.0.0.1:9010/lis/" + formatDate + "/" + patientId + "/" + i + "." + base64File.getType().toLowerCase(Locale.ROOT);
                    String base64 = base64File.getBase64();
                    byte[] decode = Base64.getDecoder().decode(base64);
                    FileUtil.writeBytes(decode, filePath);
                    urls.add(httpUrl);
                    i++;
                }
                String fileKey = testFormPdf.getMachineId() + "|" + testFormPdf.getSampleId() + "|" + testFormPdf.getTestDate();
                fileKeys.add(fileKey);
                httpUrlsMap.put(fileKey, urls);
                testFormPdfsMap.put(fileKey, testFormPdf);
                count += urls.size();
            } catch (Exception ex) {
                log.error("梅州中医院Lis采集，住院号：" + inpatientNo + ",住院流水号：" + jzh + "，type=" + testFormPdf.getType()
                        + "，machineId=" + testFormPdf.getMachineId() + ",sampleId=" + testFormPdf.getSampleId() + ",testDate=" + testFormPdf.getTestDate()
                        + ",采集base64出现错误," + ex.getMessage(), ex);
                return;
            }
        }
        log.info("住院号：{},住院流水号：{}，采集了 {} 份文件。", inpatientNo, jzh, count);
        if (!isPreventInvalidFile(patientId)) {
            tBasicMapper.invalidFileBySource(patientId, collectorId);
        }
        ReportDownPatientDto patient = new ReportDownPatientDto();
        patient.setPatientid(patientId);

        ReportDownDto reportDownDto = new ReportDownDto();
        reportDownDto.setCollectorid(collectorId);
        reportDownDto.setIp("java-lis-job");
        reportDownDto.setPatient(patient);


        for (String fileKey : fileKeys) {
            MzZyyTestDto testDto = testFormPdfsMap.get(fileKey);
            List<String> httpUrls = httpUrlsMap.get(fileKey);
            String urls = String.join("|", httpUrls);
            String fileTitle = testDto.getHisItemNameList();
            ReportDownScanFileDto reportDownScanFileDto = new ReportDownScanFileDto();
            reportDownScanFileDto.setFiletype(1);
            reportDownScanFileDto.setDownurl(urls);
            reportDownScanFileDto.setFiletitle(fileTitle);
            reportDownScanFileDto.setSerialnum(fileKey);
            reportDownScanFileDto.setFilesource(1);
            reportDownScanFileDto.setFilestoragetype(1);
            reportDownScanFileDto.setTaskid(task.getTaskId());
            reportDownScanFileDto.setSort(0);
            List<ReportDownScanFileDto> scanFiles = Collections.singletonList(reportDownScanFileDto);
            reportDownDto.setAssortid(assortId);
            reportDownDto.setScanfiles(scanFiles);
            downPlatformService.report(reportDownDto);
        }
    }


    @XxlJob("MzZyyShouMaCollectJob")
    public void shouMaCollectJob() {
        String configPath = "data-config";
        String configName = "mzzyy-ws-config";
        TableJsonRead jsonReader = new TableJsonRead();
        JSONObject configOjb = jsonReader.Read(configPath, configName, JSONObject.class);
        JSONObject shouMaConfig = configOjb.getJSONObject("shouMa");
        String collectorId = shouMaConfig.getString("collectorId");
        String hospCode = shouMaConfig.getString("hospCode");
        String branchCode = shouMaConfig.getString("branchCode");


        CommonResult<ReportDownTwoDto> commonResult = taskDistributeService.getNoViewTaskByCollectorId(collectorId);
        if (!ResultCode.SUCCESS.getCode().equals(commonResult.getCode())
                || commonResult.getData() == null) {
            return;
        }
        ReportDownTwoDto downTwoDto = commonResult.getData();
        ReportTaskTwoDto task = downTwoDto.getTasks().get(0);
        log.info(">>>>>>>>>>>>>>>>>>>>>> 梅州中医院手麻采集任务，获取了任务：{}", Func.toJson(task));
        ReportPatientTwoDto reportPatientTwoDto = downTwoDto.getPatient();
        String jzh = downTwoDto.getJzh();
        String patientId = downTwoDto.getPatientId();
        String inpatientNo = reportPatientTwoDto.getInpatientNo();

        String formatDate = Func.formatDate(new Date());
        String fileDirPath = TableJsonRead.currentPath(StaticResourceMapping.STATIC_RESOURCE_PREFIX + File.separator + StaticResourceMapping.SHOU_MA)
                + File.separator + formatDate
                + File.separator + patientId;
        MzZyyShouMaQueryMedicalDocumentInfoDto queryMedicalDocumentInfoDto = new MzZyyShouMaQueryMedicalDocumentInfoDto();
        queryMedicalDocumentInfoDto.setHospCode(hospCode);
        queryMedicalDocumentInfoDto.setBranchCode(branchCode);
        queryMedicalDocumentInfoDto.setInPatientSeqNo(jzh);
        MzZyyShouMaMedicalDocumentInfoDto queryMedicalDocumentInfoList = mzZyyShouMaService.queryMedicalDocumentInfoList(queryMedicalDocumentInfoDto);
        // 查询文书列表，为空|状态不为ok|数据为空 结束
        if (Objects.isNull(queryMedicalDocumentInfoList) ||
                !"ok".equals(queryMedicalDocumentInfoList.getStatus()) ||
                Func.isEmpty(queryMedicalDocumentInfoList.getData())) {
            if (!Objects.isNull(queryMedicalDocumentInfoList)) {
                log.info("住院号：{},住院流水号：{}，查询手麻医疗文书列表为空，返回信息为：{}。", inpatientNo, jzh, Func.toJson(queryMedicalDocumentInfoList));
            }
            determineAndCancelTask(patientId, collectorId);
            return;
        }
        List<ReportDownScanFileDto> scanFiles = new ArrayList<>();

        List<MzZyyShouMaMedicalDocumentInfoDto.Data> documentInfoListData = queryMedicalDocumentInfoList.getData();
        for (MzZyyShouMaMedicalDocumentInfoDto.Data documentInfoListDatum : documentInfoListData) {
            String reportId = documentInfoListDatum.getReportId();
            String reportTypeName = documentInfoListDatum.getReportTypeName();
            MzZyyShouMaMedicalDocumentFileForBase64Dto medicalDocumentFileForBase64 = mzZyyShouMaService.getMedicalDocumentFileForBase64(reportId);
            if (Objects.isNull(medicalDocumentFileForBase64) ||
                    !"ok".equals(medicalDocumentFileForBase64.getStatus()) ||
                    Objects.isNull(medicalDocumentFileForBase64.getData())) {
                if (!Objects.isNull(medicalDocumentFileForBase64)) {
                    log.info("手麻医疗文书,reportId:{} 获取pdf为空，返回信息为：{}。", reportId, Func.toJson(medicalDocumentFileForBase64));
                }
                continue;
            }
            MzZyyShouMaMedicalDocumentFileForBase64Dto.Data base64Data = medicalDocumentFileForBase64.getData();
            String fileBase64 = base64Data.getFileBase64();
            String fileType = base64Data.getFileType();
            String filePath = fileDirPath + File.separator + reportId + "." + fileType.toLowerCase(Locale.ROOT);
            String httpUrl = "http://127.0.0.1:9010/shouma/" + formatDate + "/" + patientId + "/" + reportId + "." + fileType.toLowerCase(Locale.ROOT);
            byte[] decode = Base64.getDecoder().decode(fileBase64);
            FileUtil.writeBytes(decode, filePath);

            ReportDownScanFileDto scanFileDto = new ReportDownScanFileDto();
            scanFileDto.setFiletype(1);
            scanFileDto.setDownurl(httpUrl);
            scanFileDto.setFiletitle(reportTypeName);
            scanFileDto.setSerialnum(reportId);
            scanFileDto.setFilesource(1);
            scanFileDto.setFilestoragetype(1);
            scanFileDto.setTaskid(task.getTaskId());
            scanFiles.add(scanFileDto);
        }
        log.info("住院号：{},住院流水号：{}，采集了 {} 份文件。", inpatientNo, jzh, scanFiles.size());
        if (Func.isNotEmpty(scanFiles)) {
            ReportDownPatientDto patient = new ReportDownPatientDto();
            patient.setPatientid(patientId);

            ReportDownDto reportDownDto = new ReportDownDto();
            reportDownDto.setCollectorid(collectorId);
            reportDownDto.setIp("java-shouma-job");
            reportDownDto.setPatient(patient);
            if (!isPreventInvalidFile(patientId)) {
                tBasicMapper.invalidFileBySource(patientId, collectorId);
            }
            for (ReportDownScanFileDto scanFile : scanFiles) {
                List<ReportDownScanFileDto> scanFileDtos = Collections.singletonList(scanFile);
                String assortId = getShouMaAssortId(scanFile.getFiletitle());
                if (Objects.isNull(assortId)) {
                    continue;
                }
                reportDownDto.setAssortid(assortId);
                reportDownDto.setScanfiles(scanFileDtos);
                downPlatformService.report(reportDownDto);
            }
        }
    }


    @XxlJob("MzZyyXinDianCollectJob")
    public void xinDianCollectJob() {
        log.info(">>>>>>>>>>>>>>>>>>>>>> 梅州中医院心电视图采集任务开始！");
        try {
            // 1.获取任务和患者信息 2.查询视图信息 3.上报下载
            String jobParam = XxlJobHelper.getJobParam();
            JSONObject jobParamJsonObject = JSONObject.parseObject(jobParam);
            String assortId = jobParamJsonObject.getString("assortId");
            String collectorId = jobParamJsonObject.getString("collectorId");
            String extraCondition = jobParamJsonObject.getString("extraCondition");
            if (Func.isBlank(assortId) || Func.isBlank(collectorId)) {
                log.warn(">>>>>>>>>>>>>>>>>>>>>> 梅州中医院心电视图采集任务,未配置心电采集器和采集文件分段");
                return;
            }
            CommonResult<ReportDownTwoDto> commonResult = taskDistributeService.getNoViewTaskByCollectorId(collectorId);
            if (ResultCode.SUCCESS.getCode().equals(commonResult.getCode())
                    && commonResult.getData() != null) {
                ReportDownTwoDto downTwoDto = commonResult.getData();
                ReportTaskTwoDto task = downTwoDto.getTasks().get(0);
                log.info("梅州中医院心电视图采集,获取了任务：{}", Func.toJson(task));

                String patientId = downTwoDto.getPatientId();
                String jzh = downTwoDto.getJzh();

                List<MzZyyXinDianView> xinDianViews = xinDianViewMapper.getPatientXinDianView(jzh, extraCondition);
                int size = xinDianViews.size();
                log.info("梅州中医院心电视图采集，记账号：{} 采集心电数据：{} 条！", jzh, size);
                if (size <= 0) {
                    determineAndCancelTask(patientId, collectorId);
                    return;
                }
                if (!isPreventInvalidFile(patientId)) {
                    tBasicMapper.invalidFileBySource(patientId, collectorId);
                }

                ReportDownPatientDto patient = new ReportDownPatientDto();
                patient.setPatientid(patientId);

                ReportDownDto reportDownDto = new ReportDownDto();
                reportDownDto.setAssortid(assortId);
                reportDownDto.setCollectorid(collectorId);
                reportDownDto.setIp("");
                reportDownDto.setPatient(patient);

                for (MzZyyXinDianView result : xinDianViews) {
                    ReportDownScanFileDto reportDownScanFileDto = new ReportDownScanFileDto();
                    reportDownScanFileDto.setDownurl(result.getBgdz());
                    reportDownScanFileDto.setFiletitle(result.getBgmc());
                    reportDownScanFileDto.setSerialnum(result.getBgid());
                    reportDownScanFileDto.setFilesource(1);
                    reportDownScanFileDto.setFiletype(1);
                    reportDownScanFileDto.setFilestoragetype(1);
                    reportDownScanFileDto.setTaskid(task.getTaskId());
                    List<ReportDownScanFileDto> scanFiles = Collections.singletonList(reportDownScanFileDto);
                    reportDownDto.setScanfiles(scanFiles);
                    downPlatformService.report(reportDownDto);
                }
            }
        } catch (Exception ex) {
            log.error(">>>>>>>>>>>>>>>>>>>>>> 梅州中医院心电视图采集任务出错了！" + ex.getMessage(), ex);
        }

        log.info(">>>>>>>>>>>>>>>>>>>>>> 梅州中医院心电视图采集任务结束！");

    }

    /**
     * 判定出院大于8天，则作废任务
     *
     * @param patientId   病案主键
     * @param collectorId 采集器id
     * @date 2025/6/4 0004 9:03
     * @author YongBin Wen
     */
    private void determineAndCancelTask(String patientId, String collectorId) {
        List<TBasic> tbasics = tBasicMapper.getTbasicByPatientIds(Collections.singletonList(patientId));
        if (Func.isEmpty(tbasics)) {
            return;
        }
        TBasic tBasic = tbasics.get(0);
        Date disDate = tBasic.getDisDate();
        if (Objects.isNull(disDate)) {
            return;
        }
        LocalDateTime disDateLocalDateTime = disDate.toInstant()
                .atZone(ZoneId.systemDefault())
                .toLocalDateTime();
        if (disDateLocalDateTime.getYear() < 1900) {
            return;
        }
        final int cancelDays = 8;
        LocalDateTime endLocalDateTime = disDateLocalDateTime.plusDays(cancelDays);
        // 现在时间大于出院n天，作废任务
        if (!LocalDateTime.now().isBefore(endLocalDateTime)) {
            tBasicMapper.cancelTask(patientId, collectorId);
        }
    }


    /**
     * 根据手麻的文件类型，得到归档的文件分段，有些文件不需要采集，则返回空
     *
     * @param fileTitle 文件类型标题
     * @return 归档的文件分段
     */
    private String getShouMaAssortId(String fileTitle) {
        String configPath = "data-config";
        String configName = "mzzyy-assort-config";
        TableJsonRead jsonReader = new TableJsonRead();
        JSONObject configOjb = jsonReader.Read(configPath, configName, JSONObject.class);
        JSONObject shouMa = configOjb.getJSONObject("shouMa");
        String defaultAssort = shouMa.getString("defaultAssort");
        JSONArray notCollect = shouMa.getJSONArray("notCollect");
        List<String> notCollectTitles = notCollect.toJavaList(String.class);
        JSONArray assort = shouMa.getJSONArray("assort");
        List<JSONObject> assortConfigs = assort.toJavaList(JSONObject.class);

        for (String notCollectTitle : notCollectTitles) {
            if (fileTitle.contains(notCollectTitle)) {
                return null;
            }
        }
        for (JSONObject assortConfig : assortConfigs) {
            String title = assortConfig.getString("title");
            String assortId = assortConfig.getString("assortId");
            String[] titles = title.split("\\|");
            for (String t : titles) {
                if (fileTitle.toLowerCase(Locale.ROOT).contains(t.toLowerCase(Locale.ROOT))) {
                    return assortId;
                }
            }
        }
        return defaultAssort;
    }

    private boolean isPreventInvalidFile(String patientId) {
        PatientState state = tBasicMapper.getPatientState(patientId);
        if (Func.isNull(state)) {
            throw new BaseException("患者不存在");
        }
        if (Func.isBlank(preventInvalidFile)) {
            return false;
        }
        // 封存、锁定、归档 符合阻止作废条件则返回true
        String[] prevents = preventInvalidFile.toLowerCase().split(",");
        List<String> preventList = Arrays.asList(prevents);
        if (preventList.contains("seal")) {
            Integer isSeal = 1;
            if (isSeal.equals(state.getIsSeal())) {
                return true;
            }
        }
        if (preventList.contains("lock")) {
            Integer isLock = 3;
            if (isLock.equals(state.getIsLock())) {
                return true;
            }
        }
        if (preventList.contains("archive")) {
            Integer isArchive = 1;
            if (isArchive.equals(state.getIsArchive())) {
                return true;
            }
        }
        return false;
    }

    public static void main(String[] args) {
        System.out.println(new MzZyyReportCollectJob().getShouMaAssortId("手术登记"));
    }

}
