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

import com.docus.core.util.Func;
import com.docus.infrastructure.core.exception.BaseException;
import com.docus.infrastructure.redis.service.IdService;
import com.docus.server.archive.constans.SyncConstant;
import com.docus.server.archive.converter.GzZxyJhPatientInfoConverter;
import com.docus.server.archive.entity.TBasic;
import com.docus.server.archive.mapper.TBasicMapper;
import com.docus.server.archive.rpc.GzZxyJhBasicDataService;
import com.docus.server.archive.rpc.dto.HisSqlInPatient01Dto;
import com.docus.server.archive.service.PatientInfoSyncService;
import com.docus.server.archive.utils.MethodRetryUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 广州中西医结合医院质控患者基础数据同步
 *
 * @author YongBin Wen
 * @date 2024/8/23 10:56
 */
@Service("gzzxyjhqc" + SyncConstant.PATIENT_INFO_SYNC_SERVICE_SUFFIX)
@Slf4j
public class GzZxyJhQcPatientInfoSyncServiceImpl implements PatientInfoSyncService {
    @Resource
    private TBasicMapper tBasicMapper;

    @Resource
    private IdService idService;

    @Resource
    private GzZxyJhBasicDataService gzZxyJhBasicDataService;


    @Override
    public void syncByDisDateRange(LocalDate start, LocalDate end) {
        LocalDate startDate = start;
        LocalDate endDate = end;
        String endDateStr = end.toString();
        String startDateStr = start.toString();
        int everyDayRetries = 20;
        while (!endDate.isBefore(startDate)) {
            // 同步与重试
            String dateStr = startDate.toString();
            try {
                syncByDisDate(startDate);
            } catch (Exception ex) {
                log.info("广州中西医结合同步质控患者，出院日期：" + dateStr + " 出错了，进行 " + everyDayRetries + "次重试," + ex.getMessage(), ex);
                boolean retryStatus = MethodRetryUtil.retry(this::syncByDisDate, startDate, everyDayRetries, 500);
                if (!retryStatus) {
                    throw new BaseException("广州中西医结合同步质控患者，出院日期：" + dateStr + "，多次（" + everyDayRetries + "）重试失败了！");
                }
            }

            startDate = startDate.plusDays(1);
        }

    }


    @Override
    public void syncByModifyTimeRange(LocalDateTime start, LocalDateTime end) {
        log.error("广州中西医结合医院未开发按照视图最后修改时间同步患者基础数据！");
    }

    @Override
    public void syncByModifyTimeAndCyrq(String cyrqStart, String startTime) {
        log.error("广州中西医结合医院未开发按照出院时间和最后修改时间同步患者基础数据！");
    }


    private void syncByDisDate(LocalDate date) {
        HisSqlInPatient01Dto hisSqlInPatient01Dto = new HisSqlInPatient01Dto();
        hisSqlInPatient01Dto.setBEGIN_TIME(date + " 00:00:00");
        hisSqlInPatient01Dto.setEND_TIME(date + " 23:59:59");
        String result = gzZxyJhBasicDataService.getHisSqlInPatient01(hisSqlInPatient01Dto);
        List<TBasic> tBasicList = GzZxyJhPatientInfoConverter.convertTbasic(result);
        // 因为扫描也同步了一套，为了区分，修改为jzh_1
        for (TBasic tBasic : tBasicList) {
            String jzh = tBasic.getJzh();
            tBasic.setJzh(jzh + "_1");
            tBasic.setFileSource(1);
            tBasic.setIsArchive(0);
        }
        saveOrUpdate(tBasicList);
    }


    /**
     * @param iuBasicList 修改的患者基础信息
     */
    private void saveOrUpdate(List<TBasic> iuBasicList) {
        Date nowDate = new Date();
        List<String> iuJzhList = iuBasicList.stream()
                .map(TBasic::getJzh)
                .collect(Collectors.toList());
        List<TBasic> existsBasicList = tBasicMapper.getByJzh(iuJzhList);
        Map<String, TBasic> existsJzhBasicMap = existsBasicList.stream().collect(Collectors.toMap(TBasic::getJzh, Function.identity()));
        List<TBasic> insertBasicList = new ArrayList<>();
        List<TBasic> updateBasicList = new ArrayList<>();

        for (TBasic iuBasic : iuBasicList) {
            if (existsJzhBasicMap.containsKey(iuBasic.getJzh())) {
                TBasic tBasic = existsJzhBasicMap.get(iuBasic.getJzh());
                tBasic.setName(iuBasic.getName());
                tBasic.setInpatientNo(iuBasic.getInpatientNo());
                tBasic.setAdmissTimes(iuBasic.getAdmissTimes());
                tBasic.setSex(iuBasic.getSex());
                tBasic.setSexName(iuBasic.getSexName());
                tBasic.setNameSpell(iuBasic.getNameSpell());
                tBasic.setJzh(iuBasic.getJzh());
                tBasic.setAdmissDate(iuBasic.getAdmissDate());
                tBasic.setAdmissDept(iuBasic.getAdmissDept());
                tBasic.setAdmissDeptName(iuBasic.getAdmissDeptName());
                tBasic.setBedNo(iuBasic.getBedNo());
                tBasic.setAttending(iuBasic.getAttending());
                tBasic.setAttendingName(iuBasic.getAttendingName());
                tBasic.setAge(iuBasic.getAge());
                tBasic.setAgeMonth(iuBasic.getAgeMonth());
                tBasic.setAgeDay(iuBasic.getAgeDay());
                tBasic.setIdCard(iuBasic.getIdCard());
                tBasic.setTelphone(iuBasic.getTelphone());
                tBasic.setDisDate(iuBasic.getDisDate());
                tBasic.setDisDept(iuBasic.getDisDept());
                tBasic.setDisDeptName(iuBasic.getDisDeptName());
                tBasic.setIsDead(iuBasic.getIsDead());
                tBasic.setTotalCost(iuBasic.getTotalCost());
                tBasic.setFileSource(iuBasic.getFileSource());
                tBasic.setGroundingNo(iuBasic.getGroundingNo());
                tBasic.setUpdateTime(nowDate);
                updateBasicList.add(tBasic);
                continue;
            }
            iuBasic.setPatientId(String.valueOf(idService.getDateSeq()));
            iuBasic.setCreateTime(nowDate);
            iuBasic.setUpdateTime(nowDate);
            iuBasic.setIsOther(0);
            insertBasicList.add(iuBasic);
        }

        if (Func.isNotEmpty(insertBasicList)) {
            tBasicMapper.insertBatch(insertBasicList);
        }
        if (Func.isNotEmpty(updateBasicList)) {
            tBasicMapper.updateBatch(updateBasicList);
        }

    }
}
