package thyyxxk.webserver.service.outpatient.interactive.clinicsatisfied;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import thyyxxk.webserver.config.exception.ExceptionEnum;
import thyyxxk.webserver.dao.his.outpatient.interactive.clinicsatisfied.ClinicSatisfiedDao;
import thyyxxk.webserver.entity.ResultVo;
import thyyxxk.webserver.entity.outpatient.interactive.clinicsatisfied.request.ClinicSatisfiedInquiry;
import thyyxxk.webserver.entity.outpatient.interactive.clinicsatisfied.request.ModifyStatus;
import thyyxxk.webserver.entity.outpatient.interactive.clinicsatisfied.request.VisitType;
import thyyxxk.webserver.entity.outpatient.interactive.clinicsatisfied.response.*;
import thyyxxk.webserver.utils.ResultVoUtil;
import thyyxxk.webserver.utils.StringUtil;
import thyyxxk.webserver.utils.TokenUtil;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;
import java.util.Objects;

@Service
public class ClinicSatisfiedService {
    private final ClinicSatisfiedDao dao;
    private static final JSONObject mainAnswers;
    private static final JSONArray checkboxOptions = new JSONArray();

    static {
        String mainAnswerString = "{\"A\": \"满意。\",\"B\": \"不满意：\",\"C\": \"未接触。\"}";

        // index:0 问题 item1，item3，item5，item7，item9，item13；住院 item9，item13，item15，item17，item19，item21
        String outpatientCheckboxOptionString = "{\"A\": \"叫号服务\",\"B\": \"等待时长\",\"C\": \"服务态度\",\"D\": \"沟通解释\",\"E\": \"及时响应\",\"F\": \"服装礼仪\",\"G\": \"准确率\"}";
        // index:1 问题 item11
        String outpatientCheckboxOptionString2 = "{\"A\": \"技术水平\",\"B\": \"隐私保护\",\"C\": \"服务态度\",\"D\": \"沟通解释\",\"E\": \"按时坐诊\",\"F\": \"服装礼仪\"}";

        // index:2 问题 item1
        String inpatientCheckboxOptionString = "{\"A\": \"技术水平\",\"B\": \"隐私保护\",\"C\": \"服务态度\",\"D\": \"沟通解释\",\"E\": \"病情巡视\",\"F\": \"服装礼仪\",\"G\": \"其他\"}";
        // index:3 问题 item3，item11
        String inpatientCheckboxOptionString2 = "{\"A\": \"技术水平\",\"B\": \"隐私保护\",\"C\": \"服务态度\",\"D\": \"沟通解释\",\"E\": \"按时查房\",\"F\": \"服装礼仪\",\"G\": \"其他\"}";
        // index:4 问题 item5
        String inpatientCheckboxOptionString3 = "{\"A\": \"卫生情况\",\"B\": \"布局不合理\",\"C\": \"服务态度\",\"D\": \"舒适度\",\"E\": \"按时清理\",\"F\": \"服装礼仪\",\"G\": \"其他\"}";
        // index:5 问题 item7
        String inpatientCheckboxOptionString4 = "{\"A\": \"卫生情况\",\"B\": \"口味\",\"C\": \"菜品\",\"D\": \"服务态度\",\"E\": \"服装礼仪\",\"F\": \"其他\"}";

        mainAnswers = JSONObject.parseObject(mainAnswerString);

        checkboxOptions.add(JSONObject.parseObject(outpatientCheckboxOptionString));
        checkboxOptions.add(JSONObject.parseObject(outpatientCheckboxOptionString2));

        checkboxOptions.add(JSONObject.parseObject(inpatientCheckboxOptionString));
        checkboxOptions.add(JSONObject.parseObject(inpatientCheckboxOptionString2));
        checkboxOptions.add(JSONObject.parseObject(inpatientCheckboxOptionString3));
        checkboxOptions.add(JSONObject.parseObject(inpatientCheckboxOptionString4));
    }

    @Autowired
    public ClinicSatisfiedService(ClinicSatisfiedDao dao) {
        this.dao = dao;
    }

    public ResultVo<SatisfiedResponse> getSatisfiedBodies(ClinicSatisfiedInquiry inquiry) {
        QueryWrapper<?> wrapper = makeQueryWrapper(inquiry);
        String table = inquiry.getVisitType() == VisitType.INPATIENT ?
                "t_inpatient_satisfied_assessment" : "t_clinic_satisfied_assessment";
        List<SatisfiedBody> list = dao.selectSatisfiedBodies(wrapper, inquiry.getPageNum(), inquiry.getPageSize(), table);
        if (list.isEmpty()) {
            return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST);
        }
        analyzeAssessmentItems(inquiry.getVisitType(), list);
        SatisfiedResponse response = new SatisfiedResponse();
        response.setVisitType(inquiry.getVisitType());
        response.setTotalSize(dao.selectValidCount(wrapper, table));
        response.setList(list);
        return ResultVoUtil.success(response);
    }

    public ResultVo<List<SatisfiedBody>> getAllSatisfiedBodies(ClinicSatisfiedInquiry inquiry) {
        QueryWrapper<?> wrapper = makeQueryWrapper(inquiry);
        String table = inquiry.getVisitType() == VisitType.INPATIENT ?
                "t_inpatient_satisfied_assessment" : "t_clinic_satisfied_assessment";
        List<SatisfiedBody> list = dao.selectAllSatisfiedBodies(wrapper, table);
        if (list.isEmpty()) {
            return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST);
        }
        analyzeAssessmentItems(inquiry.getVisitType(), list);
        return ResultVoUtil.success(list);
    }

    private QueryWrapper<?> makeQueryWrapper(ClinicSatisfiedInquiry inquiry) {
        QueryWrapper<?> wrapper = new QueryWrapper<>();
        wrapper.apply("1=1");
        if (null != inquiry.getDeleted()) {
            wrapper.eq("deleted", inquiry.getDeleted());
        }
        if (StringUtil.notBlank(inquiry.getStart())) {
            wrapper.ge("create_datetime", inquiry.getStart());
        }
        if (StringUtil.notBlank(inquiry.getEnd())) {
            wrapper.le("create_datetime", inquiry.getEnd());
        }
        if (inquiry.getOnlyShowUnsatisfied()) {
            String header = "(item1='B' or item3='B' or item5='B' or item7='B' or item9='B' or item11='B' or item13='B'";
            String tail = inquiry.getVisitType() == VisitType.OUTPATIENT ? ")" :
                    " or item15='B' or item17='B' or item19='B' or item21='B')";
            wrapper.apply(header + tail);
        }
        return wrapper;
    }

    private void analyzeAssessmentItems(VisitType visitType, List<SatisfiedBody> list) {
        if (visitType == VisitType.OUTPATIENT) {
            list.forEach(item -> {
                item.setItem1(combineAnswerAndOptions(item.getItem1(), item.getItem2(), 0));
                item.setItem3(combineAnswerAndOptions(item.getItem3(), item.getItem4(), 0));
                item.setItem5(combineAnswerAndOptions(item.getItem5(), item.getItem6(), 0));
                item.setItem7(combineAnswerAndOptions(item.getItem7(), item.getItem8(), 0));
                item.setItem9(combineAnswerAndOptions(item.getItem9(), item.getItem10(), 0));
                item.setItem11(combineAnswerAndOptions(item.getItem11(), item.getItem12(), 1));
                item.setItem13(combineAnswerAndOptions(item.getItem13(), item.getItem14(), 0));
            });
        } else {
            list.forEach(item -> {
                item.setItem1(combineAnswerAndOptions(item.getItem1(), item.getItem2(), 2));
                item.setItem3(combineAnswerAndOptions(item.getItem3(), item.getItem4(), 3));
                item.setItem5(combineAnswerAndOptions(item.getItem5(), item.getItem6(), 4));
                item.setItem7(combineAnswerAndOptions(item.getItem7(), item.getItem8(), 5));
                item.setItem9(combineAnswerAndOptions(item.getItem9(), item.getItem10(), 3));
                item.setItem11(combineAnswerAndOptions(item.getItem11(), item.getItem12(), 3));
                item.setItem13(combineAnswerAndOptions(item.getItem13(), item.getItem14(), 0));
                item.setItem15(combineAnswerAndOptions(item.getItem15(), item.getItem16(), 0));
                item.setItem17(combineAnswerAndOptions(item.getItem17(), item.getItem18(), 0));
                item.setItem19(combineAnswerAndOptions(item.getItem19(), item.getItem20(), 0));
                item.setItem21(combineAnswerAndOptions(item.getItem21(), item.getItem22(), 0));
            });
        }
    }

    private String combineAnswerAndOptions(String answer, String options, int optionIndex) {
        if (StringUtil.isBlank(answer)) {
            return "";
        }
        String transferredAnswer = mainAnswers.getString(answer);
        if (!answer.equals("B")) {
            return transferredAnswer;
        }
        return transferredAnswer + analyzedCheckboxOptions(options, optionIndex);
    }

    private String analyzedCheckboxOptions(String checkboxString, int optionIndex) {
        if (StringUtil.isBlank(checkboxString)) {
            return "";
        }
        JSONObject options = checkboxOptions.getJSONObject(optionIndex);
        String[] arr = checkboxString.split("\\^");
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < arr.length - 1; i ++) {
            builder.append(options.getString(arr[i])).append("；");
        }
        builder.append(options.getString(arr[arr.length - 1])).append("。");
        return builder.toString();
    }

    public ResultVo<String> updateAssessmentStatus(ModifyStatus modifyStatus) {
        String table = modifyStatus.getVisitType() == VisitType.INPATIENT ?
                "t_inpatient_satisfied_assessment" : "t_clinic_satisfied_assessment";
        modifyStatus.setTable(table);
        if (modifyStatus.getDeleted() == 1) {
            modifyStatus.setStaff(TokenUtil.getInstance().getTokenUserId());
            modifyStatus.setDate(new Date());
        }
        int count = dao.updateAssessmentStatus(modifyStatus);
        if (count == 1) {
            return ResultVoUtil.success("操作成功。");
        }
        return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST);
    }

    public ResultVo<AnalyzeResult> assessmentsAnalyse(ClinicSatisfiedInquiry inquiry) {
        QueryWrapper<?> wrapper = makeQueryWrapper(inquiry);
        AnalyzeResult result = new AnalyzeResult();
        VisitType visitType = inquiry.getVisitType();
        String table = visitType == VisitType.INPATIENT ?
                "t_inpatient_satisfied_assessment" : "t_clinic_satisfied_assessment";
        List<BriefSuggestion> suggestions = dao.selectSuggestions(wrapper, table);
        suggestions.removeIf(item -> item.getSuggestion().length() < 5);
        result.setSuggestions(suggestions);
        List<SatisfiedBody> list = dao.selectAllSatisfiedBodies(wrapper, table);
        result.setTotalAssessmentsCount(list.size());
        if (!inquiry.getOnlyShowUnsatisfied()) {
            inquiry.setOnlyShowUnsatisfied(true);
            wrapper = makeQueryWrapper(inquiry);
        }
        result.setTotalUnsatisfiedCount(dao.selectUnsatisfiedCount(wrapper, table));
        result.setTotalUnsatisfiedPercentage(makePercentage(result.getTotalUnsatisfiedCount(),result.getTotalAssessmentsCount()));
        int totalOptionCount = 0;
        int totalUnsatisfiedOptionCount = 0;
        int yjkAssessmentCount = 0;
        int yjkUnsatisfiedCount = 0;
        int fskAssessmentCount = 0;
        int fskUnsatisfiedCount = 0;
        int csyxkAssessmentCount = 0;
        int csyxkUnsatisfiedCount = 0;
        int jykAssessmentCount = 0;
        int jykUnsatisfiedCount = 0;
        int sfckAssessmentCount = 0;
        int sfckUnsatisfiedCount = 0;
        int mzyhAssessmentCount = 0;
        int mzyhUnsatisfiedCount = 0;
        int jzyhAssessmentCount = 0;
        int jzyhUnsatisfiedCount = 0;
        // <-- 以下住院独有
        int hlryAssessmentCount = 0;
        int hlryUnsatisfiedCount = 0;
        int ksysAssessmentCount = 0;
        int ksysUnsatisfiedCount = 0;
        int hjwsAssessmentCount = 0;
        int hjwsUnsatisfiedCount = 0;
        int stAssessmentCount = 0;
        int stUnsatisfiedCount = 0;

        int yjkCheckedOptionsCount = 0;
        JSONObject yjkOptionsJson = JSONObject.parseObject("{\"A\": 0,\"B\": 0,\"C\": 0,\"D\": 0,\"E\": 0,\"F\": 0,\"G\": 0}");
        int fskCheckedOptionsCount = 0;
        JSONObject fskOptionsJson = JSONObject.parseObject("{\"A\": 0,\"B\": 0,\"C\": 0,\"D\": 0,\"E\": 0,\"F\": 0,\"G\": 0}");
        int csyxkCheckedOptionsCount = 0;
        JSONObject csyxkOptionsJson = JSONObject.parseObject("{\"A\": 0,\"B\": 0,\"C\": 0,\"D\": 0,\"E\": 0,\"F\": 0,\"G\": 0}");
        int jykCheckedOptionsCount = 0;
        JSONObject jykOptionsJson = JSONObject.parseObject("{\"A\": 0,\"B\": 0,\"C\": 0,\"D\": 0,\"E\": 0,\"F\": 0,\"G\": 0}");
        int sfckCheckedOptionsCount = 0;
        JSONObject sfckOptionsJson = JSONObject.parseObject("{\"A\": 0,\"B\": 0,\"C\": 0,\"D\": 0,\"E\": 0,\"F\": 0,\"G\": 0}");
        int mzyhCheckedOptionsCount = 0;
        JSONObject mzyhOptionsJson = JSONObject.parseObject("{\"A\": 0,\"B\": 0,\"C\": 0,\"D\": 0,\"E\": 0,\"F\": 0,\"G\": 0}");
        int jzyhCheckedOptionsCount = 0;
        JSONObject jzyhOptionsJson = JSONObject.parseObject("{\"A\": 0,\"B\": 0,\"C\": 0,\"D\": 0,\"E\": 0,\"F\": 0,\"G\": 0}");
        // <-- 以下住院独有
        int hlryCheckedOptionsCount = 0;
        JSONObject hlryOptionsJson = JSONObject.parseObject("{\"A\": 0,\"B\": 0,\"C\": 0,\"D\": 0,\"E\": 0,\"F\": 0,\"G\": 0}");
        int ksysCheckedOptionsCount = 0;
        JSONObject ksysOptionsJson = JSONObject.parseObject("{\"A\": 0,\"B\": 0,\"C\": 0,\"D\": 0,\"E\": 0,\"F\": 0,\"G\": 0}");
        int hjwsCheckedOptionsCount = 0;
        JSONObject hjwsOptionsJson = JSONObject.parseObject("{\"A\": 0,\"B\": 0,\"C\": 0,\"D\": 0,\"E\": 0,\"F\": 0,\"G\": 0}");
        int stCheckedOptionsCount = 0;
        JSONObject stOptionsJson = JSONObject.parseObject("{\"A\": 0,\"B\": 0,\"C\": 0,\"D\": 0,\"E\": 0,\"F\": 0,\"G\": 0}");

        for (SatisfiedBody body : list) {
            if (StringUtil.notBlank(body.getItem1()) && !body.getItem1().equals("C")) {
                totalOptionCount += 1;
                if (visitType == VisitType.OUTPATIENT) {
                    yjkAssessmentCount += 1;
                } else {
                    hlryAssessmentCount += 1;
                }
            }
            if (Objects.equals("B", body.getItem1())) {
                totalUnsatisfiedOptionCount += 1;
                if (visitType == VisitType.OUTPATIENT) {
                    yjkUnsatisfiedCount += 1;
                    yjkCheckedOptionsCount = getCheckedOptionsCount(yjkCheckedOptionsCount, yjkOptionsJson, body.getItem2());
                } else {
                    hlryUnsatisfiedCount += 1;
                    hlryCheckedOptionsCount = getCheckedOptionsCount(hlryCheckedOptionsCount, hlryOptionsJson, body.getItem2());
                }
            }
            if (StringUtil.notBlank(body.getItem3()) && !body.getItem3().equals("C")) {
                totalOptionCount += 1;
                if (visitType == VisitType.OUTPATIENT) {
                    fskAssessmentCount += 1;
                } else {
                    ksysAssessmentCount += 1;
                }
            }
            if (Objects.equals("B", body.getItem3())) {
                totalUnsatisfiedOptionCount += 1;
                if (visitType == VisitType.OUTPATIENT) {
                    fskUnsatisfiedCount += 1;
                    fskCheckedOptionsCount = getCheckedOptionsCount(fskCheckedOptionsCount, fskOptionsJson, body.getItem4());
                } else {
                    ksysUnsatisfiedCount += 1;
                    ksysCheckedOptionsCount = getCheckedOptionsCount(ksysCheckedOptionsCount, ksysOptionsJson, body.getItem4());
                }
            }
            if (StringUtil.notBlank(body.getItem5()) && !body.getItem5().equals("C")) {
                totalOptionCount += 1;
                if (visitType == VisitType.OUTPATIENT) {
                    csyxkAssessmentCount += 1;
                } else {
                    hjwsAssessmentCount += 1;
                }
            }
            if (Objects.equals("B", body.getItem5())) {
                totalUnsatisfiedOptionCount += 1;
                if (visitType == VisitType.OUTPATIENT) {
                    csyxkUnsatisfiedCount += 1;
                    csyxkCheckedOptionsCount = getCheckedOptionsCount(csyxkCheckedOptionsCount, csyxkOptionsJson, body.getItem6());
                } else {
                    hjwsUnsatisfiedCount += 1;
                    hjwsCheckedOptionsCount = getCheckedOptionsCount(hjwsCheckedOptionsCount, hjwsOptionsJson, body.getItem6());
                }
            }
            if (StringUtil.notBlank(body.getItem7()) && !body.getItem7().equals("C")) {
                totalOptionCount += 1;
                if (visitType == VisitType.OUTPATIENT) {
                    jykAssessmentCount += 1;
                } else {
                    stAssessmentCount += 1;
                }
            }
            if (Objects.equals("B", body.getItem7())) {
                totalUnsatisfiedOptionCount += 1;
                if (visitType == VisitType.OUTPATIENT) {
                    jykUnsatisfiedCount += 1;
                    jykCheckedOptionsCount = getCheckedOptionsCount(jykCheckedOptionsCount, jykOptionsJson, body.getItem8());
                } else {
                    stUnsatisfiedCount += 1;
                    stCheckedOptionsCount = getCheckedOptionsCount(stCheckedOptionsCount, stOptionsJson, body.getItem8());
                }
            }
            if (StringUtil.notBlank(body.getItem9()) && !body.getItem9().equals("C")) {
                totalOptionCount += 1;
                if (visitType == VisitType.OUTPATIENT) {
                    sfckAssessmentCount += 1;
                } else {
                    yjkAssessmentCount += 1;
                }
            }
            if (Objects.equals("B", body.getItem9())) {
                totalUnsatisfiedOptionCount += 1;
                if (visitType == VisitType.OUTPATIENT) {
                    sfckUnsatisfiedCount += 1;
                    sfckCheckedOptionsCount = getCheckedOptionsCount(sfckCheckedOptionsCount, sfckOptionsJson, body.getItem10());
                } else {
                    yjkUnsatisfiedCount += 1;
                    yjkCheckedOptionsCount = getCheckedOptionsCount(yjkCheckedOptionsCount, yjkOptionsJson, body.getItem10());
                }
            }
            if (StringUtil.notBlank(body.getItem11()) && !body.getItem11().equals("C")) {
                totalOptionCount += 1;
                if (visitType == VisitType.OUTPATIENT) {
                    mzyhAssessmentCount += 1;
                } else {
                    fskAssessmentCount += 1;
                }
            }
            if (Objects.equals("B", body.getItem11())) {
                totalUnsatisfiedOptionCount += 1;
                if (visitType == VisitType.OUTPATIENT) {
                    mzyhUnsatisfiedCount += 1;
                    mzyhCheckedOptionsCount = getCheckedOptionsCount(mzyhCheckedOptionsCount, mzyhOptionsJson, body.getItem12());
                } else {
                    fskUnsatisfiedCount += 1;
                    fskCheckedOptionsCount = getCheckedOptionsCount(fskCheckedOptionsCount, fskOptionsJson, body.getItem12());
                }
            }
            if (StringUtil.notBlank(body.getItem13()) && !body.getItem13().equals("C")) {
                totalOptionCount += 1;
                if (visitType == VisitType.OUTPATIENT) {
                    jzyhAssessmentCount += 1;
                } else {
                    csyxkAssessmentCount += 1;
                }
            }
            if (Objects.equals("B", body.getItem13())) {
                totalUnsatisfiedOptionCount += 1;
                if (visitType == VisitType.OUTPATIENT) {
                    jzyhUnsatisfiedCount += 1;
                    jzyhCheckedOptionsCount = getCheckedOptionsCount(jzyhCheckedOptionsCount, jzyhOptionsJson, body.getItem14());
                } else {
                    csyxkUnsatisfiedCount += 1;
                    csyxkCheckedOptionsCount = getCheckedOptionsCount(csyxkCheckedOptionsCount, csyxkOptionsJson, body.getItem14());
                }
            }
            if (visitType == VisitType.INPATIENT) {
                if (StringUtil.notBlank(body.getItem15()) && !body.getItem15().equals("C")) {
                    totalOptionCount += 1;
                    jykAssessmentCount += 1;
                }
                if (Objects.equals("B", body.getItem16())) {
                    totalUnsatisfiedOptionCount += 1;
                    jykUnsatisfiedCount += 1;
                    jykCheckedOptionsCount = getCheckedOptionsCount(jykCheckedOptionsCount, jykOptionsJson, body.getItem16());
                }
                if (StringUtil.notBlank(body.getItem17()) && !body.getItem17().equals("C")) {
                    totalOptionCount += 1;
                    sfckAssessmentCount += 1;
                }
                if (Objects.equals("B", body.getItem18())) {
                    totalUnsatisfiedOptionCount += 1;
                    sfckUnsatisfiedCount += 1;
                    sfckCheckedOptionsCount = getCheckedOptionsCount(sfckCheckedOptionsCount, sfckOptionsJson, body.getItem18());
                }
                if (StringUtil.notBlank(body.getItem19()) && !body.getItem19().equals("C")) {
                    totalOptionCount += 1;
                    mzyhAssessmentCount += 1;
                }
                if (Objects.equals("B", body.getItem20())) {
                    totalUnsatisfiedOptionCount += 1;
                    mzyhUnsatisfiedCount += 1;
                    mzyhCheckedOptionsCount = getCheckedOptionsCount(mzyhCheckedOptionsCount, mzyhOptionsJson, body.getItem20());
                }
                if (StringUtil.notBlank(body.getItem21()) && !body.getItem21().equals("C")) {
                    totalOptionCount += 1;
                    jzyhAssessmentCount += 1;
                }
                if (Objects.equals("B", body.getItem22())) {
                    totalUnsatisfiedOptionCount += 1;
                    jzyhUnsatisfiedCount += 1;
                    jzyhCheckedOptionsCount = getCheckedOptionsCount(jzyhCheckedOptionsCount, jzyhOptionsJson, body.getItem22());
                }
            }
        }
        result.setTotalOptionCount(totalOptionCount);
        result.setTotalUnsatisfiedOptionCount(totalUnsatisfiedOptionCount);
        result.setTotalUnsatisfiedOptionPercentage(makePercentage(totalUnsatisfiedOptionCount, totalOptionCount));
        result.setYjkAssessmentCount(yjkAssessmentCount);
        result.setFskAssessmentCount(fskAssessmentCount);
        result.setCsyxkAssessmentCount(csyxkAssessmentCount);
        result.setJykAssessmentCount(jykAssessmentCount);
        result.setSfckAssessmentCount(sfckAssessmentCount);
        result.setMzyhAssessmentCount(mzyhAssessmentCount);
        result.setJzyhAssessmentCount(jzyhAssessmentCount);
        // <-- 以下住院独有
        result.setHlryAssessmentCount(hlryAssessmentCount);
        result.setKsysAssessmentCount(ksysAssessmentCount);
        result.setHjwsAssessmentCount(hjwsAssessmentCount);
        result.setStAssessmentCount(stAssessmentCount);
        // -->

        result.setYjkUnsatisfiedCount(yjkUnsatisfiedCount);
        result.setFskUnsatisfiedCount(fskUnsatisfiedCount);
        result.setCsyxkUnsatisfiedCount(csyxkUnsatisfiedCount);
        result.setJykUnsatisfiedCount(jykUnsatisfiedCount);
        result.setSfckUnsatisfiedCount(sfckUnsatisfiedCount);
        result.setMzyhUnsatisfiedCount(mzyhUnsatisfiedCount);
        result.setJzyhUnsatisfiedCount(jzyhUnsatisfiedCount);
        // <-- 以下住院独有 
        result.setHlryUnsatisfiedCount(hlryUnsatisfiedCount);
        result.setKsysUnsatisfiedCount(ksysUnsatisfiedCount);
        result.setHjwsUnsatisfiedCount(hjwsUnsatisfiedCount);
        result.setStUnsatisfiedCount(stUnsatisfiedCount);
        // -->
        
        result.setYjkUnsatisfiedPercentage(makePercentage(yjkUnsatisfiedCount, yjkAssessmentCount));
        result.setFskUnsatisfiedPercentage(makePercentage(fskUnsatisfiedCount, fskAssessmentCount));
        result.setCsyxkUnsatisfiedPercentage(makePercentage(csyxkUnsatisfiedCount, csyxkAssessmentCount));
        result.setJykUnsatisfiedPercentage(makePercentage(jykUnsatisfiedCount, jykAssessmentCount));
        result.setSfckUnsatisfiedPercentage(makePercentage(sfckUnsatisfiedCount, sfckAssessmentCount));
        result.setMzyhUnsatisfiedPercentage(makePercentage(mzyhUnsatisfiedCount, mzyhAssessmentCount));
        result.setJzyhUnsatisfiedPercentage(makePercentage(jzyhUnsatisfiedCount, jzyhAssessmentCount));
        // <-- 以下住院独有
        result.setHlryUnsatisfiedPercentage(makePercentage(hlryUnsatisfiedCount, hlryAssessmentCount));
        result.setKsysUnsatisfiedPercentage(makePercentage(ksysUnsatisfiedCount, ksysAssessmentCount));
        result.setHjwsUnsatisfiedPercentage(makePercentage(hjwsUnsatisfiedCount, hjwsAssessmentCount));
        result.setStUnsatisfiedPercentage(makePercentage(stUnsatisfiedCount, stAssessmentCount));
        // -->
        
        result.setYjkUnsatisfiedOption(fillOptionDetails(yjkAssessmentCount, yjkCheckedOptionsCount, yjkOptionsJson, 0));
        result.setFskUnsatisfiedOption(fillOptionDetails(fskAssessmentCount, fskCheckedOptionsCount, fskOptionsJson, visitType == VisitType.OUTPATIENT ? 0 : 3));
        result.setCsyxkUnsatisfiedOption(fillOptionDetails(csyxkAssessmentCount, csyxkCheckedOptionsCount, csyxkOptionsJson, 0));
        result.setJykUnsatisfiedOption(fillOptionDetails(jykAssessmentCount, jykCheckedOptionsCount, jykOptionsJson, 0));
        result.setSfckUnsatisfiedOption(fillOptionDetails(sfckAssessmentCount, sfckCheckedOptionsCount, sfckOptionsJson, 0));
        result.setMzyhUnsatisfiedOption(fillOptionDetails(mzyhAssessmentCount, mzyhCheckedOptionsCount, mzyhOptionsJson, visitType == VisitType.OUTPATIENT ? 1 : 0));
        result.setJzyhUnsatisfiedOption(fillOptionDetails(jzyhAssessmentCount, jzyhCheckedOptionsCount, jzyhOptionsJson, 0));

        // <-- 以下住院独有
        result.setHlryUnsatisfiedOption(fillOptionDetails(hlryAssessmentCount, hlryCheckedOptionsCount, hlryOptionsJson, 2));
        result.setKsysUnsatisfiedOption(fillOptionDetails(ksysAssessmentCount, ksysCheckedOptionsCount, ksysOptionsJson, 3));
        result.setHjwsUnsatisfiedOption(fillOptionDetails(hjwsAssessmentCount, hjwsCheckedOptionsCount, hjwsOptionsJson, 4));
        result.setStUnsatisfiedOption(fillOptionDetails(stAssessmentCount, stCheckedOptionsCount, stOptionsJson, 5));
        // -->
        return ResultVoUtil.success(result);
    }

    private UnsatisfiedOption fillOptionDetails(int assessmentCount, int checkedOptionSize,
                                                JSONObject optionsJson, int checkboxOptionIndex) {
        UnsatisfiedOption unsatisfiedOption = new UnsatisfiedOption();
        JSONObject options = checkboxOptions.getJSONObject(checkboxOptionIndex);
        int totalOptionSize = assessmentCount * options.size();
        unsatisfiedOption.setTotalOptionSize(totalOptionSize);
        unsatisfiedOption.setCheckedOptionSize(checkedOptionSize);
        unsatisfiedOption.setCheckedOptionPercentage(makePercentage(checkedOptionSize, totalOptionSize));
        if (checkboxOptionIndex == 5) {
            unsatisfiedOption.setFwtdCount(optionsJson.getInteger("D"));
            unsatisfiedOption.setFzlyCount(optionsJson.getInteger("E"));
            unsatisfiedOption.setWsqkCount(optionsJson.getInteger("A"));
            unsatisfiedOption.setWsqkPercentage(makePercentage(unsatisfiedOption.getWsqkCount(), checkedOptionSize));
            unsatisfiedOption.setKwCount(optionsJson.getInteger("B"));
            unsatisfiedOption.setKwPercentage(makePercentage(unsatisfiedOption.getKwCount(), checkedOptionSize));
            unsatisfiedOption.setCpCount(optionsJson.getInteger("C"));
            unsatisfiedOption.setCpPercentage(makePercentage(unsatisfiedOption.getCpCount(), checkedOptionSize));
            unsatisfiedOption.setQtCount(optionsJson.getInteger("F"));
            unsatisfiedOption.setQtPercentage(makePercentage(unsatisfiedOption.getQtCount(), checkedOptionSize));
        } else {
            unsatisfiedOption.setFwtdCount(optionsJson.getInteger("C"));
            unsatisfiedOption.setFzlyCount(optionsJson.getInteger("F"));
        }
        unsatisfiedOption.setFwtdPercentage(makePercentage(unsatisfiedOption.getFwtdCount(), checkedOptionSize));
        unsatisfiedOption.setFzlyPercentage(makePercentage(unsatisfiedOption.getFzlyCount(), checkedOptionSize));
        if (checkboxOptionIndex != 4 && checkboxOptionIndex != 5) {
            unsatisfiedOption.setGtjsCount(optionsJson.getInteger("D"));
            unsatisfiedOption.setGtjsPercentage(makePercentage(unsatisfiedOption.getGtjsCount(), checkedOptionSize));
        }
        if (checkboxOptionIndex == 2 || checkboxOptionIndex == 3) {
            unsatisfiedOption.setJsspCount(optionsJson.getInteger("A"));
            unsatisfiedOption.setJsspPercentage(makePercentage(unsatisfiedOption.getJsspCount(), checkedOptionSize));
            unsatisfiedOption.setYsbhCount(optionsJson.getInteger("B"));
            unsatisfiedOption.setYsbhPercentage(makePercentage(unsatisfiedOption.getYsbhCount(), checkedOptionSize));
            unsatisfiedOption.setQtCount(optionsJson.getInteger("G"));
            unsatisfiedOption.setQtPercentage(makePercentage(unsatisfiedOption.getQtCount(), checkedOptionSize));
            if (checkboxOptionIndex == 2) {
                unsatisfiedOption.setBqxsCount(optionsJson.getInteger("E"));
                unsatisfiedOption.setBqxsPercentage(makePercentage(unsatisfiedOption.getBqxsCount(), checkedOptionSize));
            } else {
                unsatisfiedOption.setAscfCount(optionsJson.getInteger("E"));
                unsatisfiedOption.setAscfPercentage(makePercentage(unsatisfiedOption.getAscfCount(), checkedOptionSize));
            }
        }
        if (checkboxOptionIndex == 4) {
            unsatisfiedOption.setWsqkCount(optionsJson.getInteger("A"));
            unsatisfiedOption.setWsqkPercentage(makePercentage(unsatisfiedOption.getWsqkCount(), checkedOptionSize));
            unsatisfiedOption.setBjbhlCount(optionsJson.getInteger("B"));
            unsatisfiedOption.setBjbhlPercentage(makePercentage(unsatisfiedOption.getBjbhlCount(), checkedOptionSize));
            unsatisfiedOption.setSsdCount(optionsJson.getInteger("D"));
            unsatisfiedOption.setSsdPercentage(makePercentage(unsatisfiedOption.getSsdCount(), checkedOptionSize));
            unsatisfiedOption.setAsqlCount(optionsJson.getInteger("E"));
            unsatisfiedOption.setAsqlPercentage(makePercentage(unsatisfiedOption.getAsqlCount(), checkedOptionSize));
            unsatisfiedOption.setQtCount(optionsJson.getInteger("G"));
            unsatisfiedOption.setQtPercentage(makePercentage(unsatisfiedOption.getQtCount(), checkedOptionSize));
        }
        if (checkboxOptionIndex == 1) {
            unsatisfiedOption.setJsspCount(optionsJson.getInteger("A"));
            unsatisfiedOption.setJsspPercentage(makePercentage(unsatisfiedOption.getJsspCount(), checkedOptionSize));
            unsatisfiedOption.setYsbhCount(optionsJson.getInteger("B"));
            unsatisfiedOption.setYsbhPercentage(makePercentage(unsatisfiedOption.getYsbhCount(), checkedOptionSize));
            unsatisfiedOption.setAszzCount(optionsJson.getInteger("E"));
            unsatisfiedOption.setAszzPercentage(makePercentage(unsatisfiedOption.getAszzCount(), checkedOptionSize));
        } else if (checkboxOptionIndex == 0) {
            unsatisfiedOption.setJhfwCount(optionsJson.getInteger("A"));
            unsatisfiedOption.setJhfwPercentage(makePercentage(unsatisfiedOption.getJhfwCount(), checkedOptionSize));
            unsatisfiedOption.setDdscCount(optionsJson.getInteger("B"));
            unsatisfiedOption.setDdscPercentage(makePercentage(unsatisfiedOption.getDdscCount(), checkedOptionSize));
            unsatisfiedOption.setJsxyCount(optionsJson.getInteger("E"));
            unsatisfiedOption.setJsxyPercentage(makePercentage(unsatisfiedOption.getJsxyCount(), checkedOptionSize));
            unsatisfiedOption.setZqlCount(optionsJson.getInteger("G"));
            unsatisfiedOption.setZqlPercentage(makePercentage(unsatisfiedOption.getZqlCount(), checkedOptionSize));
        }
        return unsatisfiedOption;
    }

    private int getCheckedOptionsCount(int optionsCount, JSONObject optionsJson, String options) {
        if (StringUtil.notBlank(options)) {
            String[] arr = options.split("\\^");
            optionsCount += arr.length;
            for (String option : arr) {
                int temp = optionsJson.getIntValue(option);
                temp += 1;
                optionsJson.replace(option, temp);
            }
        }
        return optionsCount;
    }

    private String makePercentage(int a, int b) {
        if (a == 0 || b == 0) {
            return "0.00%";
        }
        BigDecimal aDecimal = new BigDecimal(a);
        BigDecimal bDecimal = new BigDecimal(b);
        BigDecimal percentage = aDecimal.multiply(new BigDecimal(100))
                .divide(bDecimal, 2, RoundingMode.HALF_UP);
        return percentage + "%";
    }
}
