package com.docus.server.synclis.service.impl;

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.enums.SysFlagType;
import com.docus.server.archive.mapper.AfCollectTaskMapper;
import com.docus.server.synclis.converter.LisViewConverter;
import com.docus.server.synclis.entity.LisView;
import com.docus.server.synclis.mapper.LisViewMapper;
import com.docus.server.synclis.service.LisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;

/**
 * @author YongBin Wen
 * @date 2025/1/16 15:06
 */
@Service
@Slf4j
public class LisServiceImpl implements LisService {
    @Resource
    private LisViewMapper lisViewMapper;
    @Resource
    private AfCollectTaskMapper afCollectTaskMapper;
    @Resource
    private IdService idService;

    private final static ReentrantLock SAVE_TASK_LOCK = new ReentrantLock();

    @Override
    public void syncViewTask(TBasic tBasic) {
        syncViewZyTask(tBasic);
        syncViewMzTask(tBasic);
    }

    @Override
    public void syncFullTask(TBasic tBasic) {
        syncFullZyTask(tBasic);
        syncFullMzTask(tBasic);
    }

    @Override
    public void revisionMzTaskAndFile(TBasic tbasic) {
        String patientId = tbasic.getPatientId();
        List<String> mzSource= Arrays.asList( "门诊","急诊");
        Date admissDate = tbasic.getAdmissDate();
        String admissDateStr = Func.formatDateTime(admissDate);
        LocalDateTime admissLocalDateTime = Func.parseDateTime(admissDateStr);
        LocalDateTime startLocalDateTime = admissLocalDateTime.plusDays(-3);
        String start = startLocalDateTime.toLocalDate().toString() + " 00:00:00";
        Date startDateTime = Func.parseDate(start,"yyyy-MM-dd HH:mm:ss");

        List<AfCollectTask> collectTasks = afCollectTaskMapper.findByPatientIds(Collections.singletonList(patientId));
        List<AfCollectTask>   mzCollectTasks=collectTasks.stream().filter(tsk->
            SysFlagType.LIS.getType().equals(tsk.getSysflag()) && mzSource.contains(tsk.getC7())
        ).collect(Collectors.toList());
        if(Func.isEmpty(mzCollectTasks)){
            return;
        }
        List<AfCollectTask> cancelTasks=new ArrayList<>();

        for (AfCollectTask mzCollectTask : mzCollectTasks) {
            Date reqDate = mzCollectTask.getT1();
            // 如果申请时间不在入院前三天范围内，则作废
            if(reqDate.after(admissDate) || reqDate.before(startDateTime)){
                cancelTasks.add(mzCollectTask);
            }

        }
        if(Func.isEmpty(cancelTasks)){
            return;
        }
        List<Long> cancelTaskIds = cancelTasks.stream().map(AfCollectTask::getId).collect(Collectors.toList());
        afCollectTaskMapper.cancelTask(cancelTaskIds);
        afCollectTaskMapper.cancelFileByTaskId(cancelTaskIds);

    }

    public static void main(String[] args) {
        TBasic tBasic = new TBasic();
        tBasic.setAdmissDate(new Date());
        new LisServiceImpl().revisionMzTaskAndFile(tBasic);
    }

    /**
     * 同步视图住院期间报告任务
     */
    private void syncViewZyTask(TBasic tBasic) {
        String inpatientNo = tBasic.getInpatientNo();
        Date admissDate = tBasic.getAdmissDate();
        Date disDate = tBasic.getDisDate();
        if (Func.isBlank(inpatientNo) || Objects.isNull(admissDate) || Objects.isNull(disDate)) {
            log.warn("LIS同步视图住院任务失败，病案号、入院日期、出院日期 有空数据！患者主键：{}", tBasic.getPatientId());
            return;
        }
        String admissDateStr = Func.formatDateTime(admissDate);
        String disDateStr = Func.formatDateTime(disDate);
        List<LisView> zyDataFromView = lisViewMapper.getZyDataFromView(inpatientNo, admissDateStr, disDateStr);
        saveTask(zyDataFromView, tBasic);
    }


    /**
     * 同步视图门急诊报告任务,入院前三天的报告
     */
    private void syncViewMzTask(TBasic tBasic) {
        String idCard = tBasic.getIdCard();
        Date admissDate = tBasic.getAdmissDate();
        if (Func.isBlank(idCard) || Objects.isNull(admissDate)) {
            log.warn("LIS同步视图门（急）诊任务失败，数据身份证号码 或者 入院日期 为空！患者主键：{}", tBasic.getPatientId());
            return;
        }
        String admissDateStr = Func.formatDateTime(admissDate);
        LocalDateTime startLocalDateTime = Func.parseDateTime(admissDateStr).plusDays(-3);
        String startLocalDateStr = startLocalDateTime.toLocalDate().toString();
        List<LisView> mzDataFromView = lisViewMapper.getMzDataFromView(idCard, startLocalDateStr, admissDateStr);
        saveTask(mzDataFromView, tBasic);
    }


    private void syncFullZyTask(TBasic tBasic) {
        String inpatientNo = tBasic.getInpatientNo();
        Date admissDate = tBasic.getAdmissDate();
        Date disDate = tBasic.getDisDate();
        if (Func.isBlank(inpatientNo) || Objects.isNull(admissDate) || Objects.isNull(disDate)) {
            log.warn("LIS同步完整住院任务失败，病案号、入院日期、出院日期 有空数据！患者主键：{}", tBasic.getPatientId());
            return;
        }
        String admissDateStr = Func.formatDateTime(admissDate);
        String disDateStr = Func.formatDateTime(disDate);
        List<LisView> zyDataFromView = lisViewMapper.getFullZyData(inpatientNo, admissDateStr, disDateStr);
        saveTask(zyDataFromView, tBasic);
    }

    private void syncFullMzTask(TBasic tBasic) {
        String idCard = tBasic.getIdCard();
        Date admissDate = tBasic.getAdmissDate();
        if (Func.isBlank(idCard) || Objects.isNull(admissDate)) {
            log.warn("LIS同步完整门（急）诊任务失败，数据身份证号码 或者 入院日期 为空！患者主键：{}", tBasic.getPatientId());
            return;
        }
        String admissDateStr = Func.formatDateTime(admissDate);
        LocalDateTime startLocalDateTime = Func.parseDateTime(admissDateStr).plusDays(-3);
        String startLocalDateStr = startLocalDateTime.toLocalDate().toString();
        List<LisView> mzDataFromView = lisViewMapper.getFullMzData(idCard, startLocalDateStr, admissDateStr);
        saveTask(mzDataFromView, tBasic);
    }

    private void saveTask(List<LisView> mzDataFromView, TBasic tBasic) {
        if (Func.isEmpty(mzDataFromView)) {
            return;
        }
        SAVE_TASK_LOCK.lock();
        try {
            List<String> patientIds = Collections.singletonList(tBasic.getPatientId());
            List<AfCollectTask> existsTasks = afCollectTaskMapper.findByPatientIds(patientIds);
            List<AfCollectTask> existsLisTasks = existsTasks.stream()
                    .filter(tsk -> SysFlagType.LIS.getType().equals(tsk.getSysflag()))
                    .collect(Collectors.toList());

            List<AfCollectTask> newTaskList = new ArrayList<>();
            List<AfCollectTask> updateTaskList = new ArrayList<>();

            for (LisView lisView : mzDataFromView) {
                AfCollectTask convertTask = LisViewConverter.convertTask(lisView, tBasic);
                AfCollectTask existsTask = findExistsTask(existsLisTasks, convertTask);
                if (existsTask == null) {
                    convertTask.setId(idService.getDateSeq());
                    convertTask.setCreateTime(new Date());
                    newTaskList.add(convertTask);
                    continue;
                }
                // 如果任务还在进行 或者 视图审核时间没有增大，不进行更新
                if ("0".equals(existsTask.getState()) || !convertTask.getT2().after(existsTask.getT2())) {
                    continue;
                }
                // 更新
                existsTask.setT1(convertTask.getT1());
                existsTask.setT2(convertTask.getT2());
                existsTask.setPresult("");
                existsTask.setSyncTime(new Date());
                updateTaskList.add(existsTask);
            }


            if (Func.isNotEmpty(newTaskList)) {
                afCollectTaskMapper.saveBatch(newTaskList);
            }
            if (Func.isNotEmpty(updateTaskList)) {
                afCollectTaskMapper.update(updateTaskList);
            }
        } catch (Exception ex) {
            log.error("保存/修改LIS任务出错了！" + ex.getMessage(), ex);
        } finally {
            SAVE_TASK_LOCK.unlock();
        }

    }

    /**
     * 从已经存在的任务中，根据条件筛选出匹配的任务
     *
     * @param existsLisTasks 存在的任务
     * @param convertTask    任务条件
     * @return 已经存在的采集任务
     */
    private AfCollectTask findExistsTask(List<AfCollectTask> existsLisTasks, AfCollectTask convertTask) {
        for (AfCollectTask existsLisTask : existsLisTasks) {
            if (existsLisTask.getC1().equals(convertTask.getC1()) &&
                    existsLisTask.getC2().equals(convertTask.getC2()) &&
                    existsLisTask.getPatientId().equals(convertTask.getPatientId()) &&
                    existsLisTask.getC3().equals(convertTask.getC3()) &&
                    existsLisTask.getC4().equals(convertTask.getC4())) {
                return existsLisTask;
            }
        }
        return null;
    }


}
