package thyyxxk.webserver.service.inpatient.casefrontsheet;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import thyyxxk.webserver.dao.his.inpatient.casefrontsheet.CaseFrontSheetAnalyzeDao;
import thyyxxk.webserver.entity.ResultVo;
import thyyxxk.webserver.entity.casefrontsheet.*;
import thyyxxk.webserver.entity.casefrontsheet.request.CountType;
import thyyxxk.webserver.entity.casefrontsheet.request.SheetAnalyzeParams;
import thyyxxk.webserver.entity.casefrontsheet.response.DismissCount;
import thyyxxk.webserver.service.hutoolcache.DeptCache;
import thyyxxk.webserver.service.hutoolcache.UserCache;
import thyyxxk.webserver.utils.*;

import java.util.*;

@Slf4j
@Service
public class CaseFrontSheetAnalyzeService {
    private static final List<String> ABOVE_GRADE_FOUR = Arrays.asList("1", "2", "3");
    private final CaseFrontSheetAnalyzeDao dao;
    private final UserCache userCache;
    private final DeptCache deptCache;

    @Autowired
    public CaseFrontSheetAnalyzeService(CaseFrontSheetAnalyzeDao dao, UserCache userCache, DeptCache deptCache) {
        this.dao = dao;
        this.userCache = userCache;
        this.deptCache = deptCache;
    }

    public ResultVo<List<DismissCount>> analyzeDismissCount(SheetAnalyzeParams param) {
        String[] dateRange = getDatetimeRangeByMonth(param.getMonth());
        param.setDept("%" + param.getDept().trim() + "%");
        List<DismissCount> list;
        if (param.getCountType() == CountType.BY_DEPARTMENT) {
            List<TempDismissCount> templist = dao.selectDismissCount(dateRange[0], dateRange[1]);
            Map<String, DismissCount> map = new HashMap<>();
            for (TempDismissCount item : templist) {
                if (map.containsKey(item.getDeptCode())) {
                    DismissCount count = map.get(item.getDeptCode());
                    count.setDismissCount(count.getDismissCount() + item.getDismissCount());
                    if (item.getFileStatus() == 1) {
                        count.setSignedCount(count.getSignedCount() + item.getDismissCount());
                    } else {
                        count.setUnsignCount(count.getUnsignCount() + item.getDismissCount());
                    }
                } else {
                    DismissCount dismissCount = new DismissCount();
                    dismissCount.setDeptName(deptCache.get(item.getDeptCode()).getName());
                    dismissCount.setDismissCount(item.getDismissCount());
                    if (item.getFileStatus() == 1) {
                        dismissCount.setSignedCount(item.getDismissCount());
                        dismissCount.setUnsignCount(0);
                    } else {
                        dismissCount.setUnsignCount(item.getDismissCount());
                        dismissCount.setSignedCount(0);
                    }
                    map.put(item.getDeptCode(), dismissCount);
                }
            }
            list = new ArrayList<>();
            for (Map.Entry<String, DismissCount> entry : map.entrySet()) {
                list.add(entry.getValue());
            }
        } else if (param.getCountType() == CountType.BY_SIGN_STAFF) {
            List<TempDismissCount> templist = dao.selectDismissCount2(dateRange[0], dateRange[1]);
            Map<String, DismissCount> map = new HashMap<>();
            int totalCount = 0;
            for (TempDismissCount item : templist) {
                totalCount += item.getDismissCount();
                if (map.containsKey(item.getSignStaff())) {
                    DismissCount count = map.get(item.getSignStaff());
                    count.setDismissCount(count.getDismissCount() + item.getDismissCount());
                } else {
                    DismissCount dismissCount = new DismissCount();
                    if (item.getSignStaff().equals("NONE")) {
                        dismissCount.setSignStaffName("未签收");
                    } else {
                        dismissCount.setSignStaffName(userCache.getEmployeeName(item.getSignStaff()));
                    }
                    dismissCount.setDismissCount(item.getDismissCount());
                    map.put(item.getSignStaff(), dismissCount);
                }
            }
            list = new ArrayList<>();
            DismissCount unSign = map.remove("NONE");
            if (null != unSign) {
                list.add(unSign);
            }
            for (Map.Entry<String, DismissCount> entry : map.entrySet()) {
                list.add(entry.getValue());
            }
            DismissCount total = new DismissCount();
            total.setSignStaff("TOTAL");
            total.setSignStaffName("合计");
            total.setDismissCount(totalCount);
            list.add(total);
        } else if (param.getCountType() == CountType.BY_DETAIL) {
            list = dao.selectDismissDetailCount(dateRange[0], dateRange[1], param.getDept());
            for (DismissCount item : list) {
                if (StringUtil.equalsIgnoreNull(item.getZkWard(), item.getAdmissDept())) {
                    item.setZkWard(null);
                }
                String staffName = StringUtil.isBlank(item.getSignStaff()) ?
                        "未签收" : userCache.getEmployeeName(item.getSignStaff());
                item.setSignStaff(staffName);
                item.setBlfx(FilterUtil.translateCaseClass(item.getBlfx()));
                item.setFdcrb(FilterUtil.translateStatutoryEpidemic(item.getFdcrb()));
            }
        } else {
            list = dao.selectDeathCount(dateRange[0], dateRange[1], param.getDept());
            for (DismissCount item : list) {
                if (StringUtil.equalsIgnoreNull(item.getZkWard(), item.getAdmissDept())) {
                    item.setZkWard(null);
                }
                item.setDisDept(deptCache.get(item.getDisDept()).getName());
                item.setBlfx(FilterUtil.translateCaseClass(item.getBlfx()));
                item.setAdmissDept(deptCache.get(item.getAdmissDept()).getName());
                item.setZkWard(deptCache.get(item.getZkWard()).getName());
                item.setKzr(userCache.getEmployeeName(item.getKzr()));
                item.setZzys(userCache.getEmployeeName(item.getZzys()));
                item.setZyys(userCache.getEmployeeName(item.getZyys()));
                item.setFdcrb(FilterUtil.translateStatutoryEpidemic(item.getFdcrb()));
            }
        }
        return ResultVoUtil.success(list);
    }

    public ResultVo<List<SheetQuality>> analyzeQualityControl(SheetAnalyzeParams params) {
        String[] dateRange = new String[2];
        if (StringUtil.isBlank(params.getYear())) {
            dateRange[0] = params.getBeginMonth() + "-01 00:00:00";
            dateRange[1] = DateUtil.getMonthEndtime(params.getEndMonth());
        } else {
            dateRange = getDatetimeRangeByYear(params.getYear());
        }
        String deptIdentity = params.getCountType() == CountType.BY_DEPARTMENT ?
                "admiss_dept" : "dismiss_dept";
        List<SheetQualitySources> qualitySources = dao.selectSheetQualitySource(dateRange[0], dateRange[1], deptIdentity);
        Map<String, List<SheetQualitySources>> deptQualitySources = new HashMap<>();
        for (SheetQualitySources sources : qualitySources) {
            if (!deptQualitySources.containsKey(sources.getDeptCode())) {
                deptQualitySources.put(sources.getDeptCode(), new ArrayList<>());
            }
            deptQualitySources.get(sources.getDeptCode()).add(sources);
        }

        List<SheetQualitySources> surgeriesList = dao.selectSheetQualitySurgeries(dateRange[0], dateRange[1]);
        Map<String, int[]> surgeryMap = new HashMap<>();
        for (SheetQualitySources surgery : surgeriesList) {
            String deptCode = surgery.getDeptCode();
            if (!surgeryMap.containsKey(deptCode)) {
                int[] surgeryCount = new int[]{0, 1};
                if (Objects.equals(surgery.getHeal(), "1")) {
                    surgeryCount[0] = 1;
                }
                surgeryMap.put(deptCode, surgeryCount);
            } else {
                if (Objects.equals(surgery.getHeal(), "1")) {
                    surgeryMap.get(deptCode)[0] += 1;
                }
                surgeryMap.get(deptCode)[1] += 1;
            }
        }

        List<SheetQuality> sheetQualities = new ArrayList<>();
        for (Map.Entry<String, List<SheetQualitySources>> entry : deptQualitySources.entrySet()) {
            String deptCode = entry.getKey();
            SheetQuality sheetQuality = new SheetQuality();
            sheetQuality.setDepartmentCode(deptCode);
            List<SheetQualitySources> tempSources = entry.getValue();
            sheetQuality.setDepartmentName(tempSources.get(0).getDeptName());

            if (surgeryMap.containsKey(deptCode)) {
                int[] surgery = surgeryMap.get(deptCode);
                sheetQuality.setSurgicalIncisionBestHealingRate(DecimalUtil.getPercent(surgery[0], surgery[1]));
            }

            int sourceSize = tempSources.size();
            Integer bednum = dao.selectOpenbedNum(deptCode);
            if (null == bednum || bednum <= 0) {
                sheetQuality.setBedTurnoverTimes("未维护科室床位数，无法计算。");
            } else {
                sheetQuality.setBedTurnoverTimes(String.valueOf(sourceSize / bednum));
            }
            int diagConformInAdmAndDischarge = 0, diagConformInPreAndAfterOperation = 0, diagConformInPreAndAfterOperationTotal = 0,
                    diagConformInMainDiagAndPathology = 0, diagConformInMainDiagAndPathologyTotal = 0, rescueTimes = 0,
                    rescueSuccessTimes = 0, medicalRecordAboveGradeFour = 0, levelFiveMedicalRecordCount = 0, inhospDays = 0;
            for (SheetQualitySources tempSource : tempSources) {
                inhospDays += tempSource.getAdmissDays();
                if (Objects.equals(tempSource.getDiagConform2(), "1")) {
                    diagConformInAdmAndDischarge += 1;
                }
                if (StringUtil.notBlank(tempSource.getDiagConform3()) && !tempSource.getDiagConform3().equals("0")) {
                    diagConformInPreAndAfterOperationTotal += 1;
                }
                if (Objects.equals(tempSource.getDiagConform3(), "1")) {
                    diagConformInPreAndAfterOperation += 1;
                }
                if (StringUtil.notBlank(tempSource.getDiagConform4()) && !tempSource.getDiagConform4().equals("0")) {
                    diagConformInMainDiagAndPathologyTotal += 1;
                }
                if (Objects.equals(tempSource.getDiagConform4(), "1")) {
                    diagConformInMainDiagAndPathology += 1;
                }
                rescueTimes += tempSource.getRescueTimes();
                rescueSuccessTimes += tempSource.getRescueSuccessTimes();
                if (StringUtil.notBlank(tempSource.getQualityControlLevel())) {
                    if (ABOVE_GRADE_FOUR.contains(tempSource.getQualityControlLevel())) {
                        medicalRecordAboveGradeFour += 1;
                    } else if (tempSource.getQualityControlLevel().equals("5")) {
                        levelFiveMedicalRecordCount += 1;
                    }
                }
            }
            sheetQuality.setDiagConformInAdmAndDischarge(DecimalUtil.getPercent(diagConformInAdmAndDischarge, sourceSize));
            if (diagConformInPreAndAfterOperationTotal > 0) {
                sheetQuality.setDiagConformInPreAndAfterOperation(DecimalUtil.getPercent(diagConformInPreAndAfterOperation, diagConformInPreAndAfterOperationTotal));
            }
            if (diagConformInMainDiagAndPathologyTotal > 0) {
                sheetQuality.setDiagConformInMainDiagAndPathology(DecimalUtil.getPercent(diagConformInMainDiagAndPathology, diagConformInMainDiagAndPathologyTotal));
            }
            if (rescueTimes > 0) {
                sheetQuality.setRescueSuccessRate(DecimalUtil.getPercent(rescueSuccessTimes, rescueTimes));
            }
            sheetQuality.setMedicalRecordRateAboveGradeFour(DecimalUtil.getPercent(medicalRecordAboveGradeFour, sourceSize));
            sheetQuality.setLevelFiveMedicalRecordRate(DecimalUtil.getPercent(levelFiveMedicalRecordCount, sourceSize));
            sheetQuality.setLevelFiveMedicalCount(levelFiveMedicalRecordCount);
            sheetQuality.setAverageLengthOfStay(inhospDays / sourceSize);
            sheetQualities.add(sheetQuality);
        }
        return ResultVoUtil.success(sheetQualities);
    }

    private String[] getDatetimeRangeByMonth(String month) {
        String begntime = month + "-01 00:00:00.000";
        String endtime = DateUtil.getMonthEndtime(month);
        return new String[]{begntime, endtime};
    }

    private String[] getDatetimeRangeByYear(String year) {
        if (year.length() > 4) {
            year = year.substring(0, 4);
        }
        String begntime = year + "-01-01 00:00:00";
        String endtime = year + "-12-31 23:59:59";
        return new String[]{begntime, endtime};
    }
}
