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.ClinicSatisfiedDao;
import thyyxxk.webserver.entity.ResultVo;
import thyyxxk.webserver.entity.inpatient.nursemodule.response.PatientBriefInfo;
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.DecimalUtil;
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；住院 item9，item15，item17，item19，item21
        String outpatientCheckboxOptionString = "{\"A\": \"叫号服务\",\"B\": \"等待时长\",\"C\": \"服务态度\",\"D\": \"沟通解释\",\"E\": \"及时响应\",\"F\": \"服装礼仪\",\"G\": \"准确率\"}";
        // index:1 问题 item13
        String outpatientCheckboxOptionString2 = "{\"A\": \"技术水平\",\"B\": \"隐私保护\",\"C\": \"服务态度\",\"D\": \"沟通解释\",\"E\": \"按时坐诊\",\"F\": \"服装礼仪\"}";
        // index:6 问题 item11
        String outpatientCheckboxOptionString3 = "{\"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\": \"其他\"}";

        // index: 7
        String whyChooseHereOptionString = "{\"A\": \"慕名而来\",\"B\": \"就近选择\",\"C\": \"朋友推荐\",\"D\": \"网络查询\",\"E\": \"服务水平\",\"F\": \"环境设备\",\"G\": \"医疗价格\"}";
        // index: 8
        String willComeAgainOptionString = "{\"A\": \"会\",\"B\": \"不会\"}";

        // index:9 问题 门诊：item15，住院：item23
        String outpatientCheckboxOptionString4 = "{\"A\": \"专业能力\",\"B\": \"等待时长\",\"C\": \"服务态度\",\"D\": \"沟通解释\",\"E\": \"及时响应\",\"F\": \"服装礼仪\",\"G\": \"服务流程\"}";

        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));
        checkboxOptions.add(JSONObject.parseObject(outpatientCheckboxOptionString3));

        checkboxOptions.add(JSONObject.parseObject(whyChooseHereOptionString));
        checkboxOptions.add(JSONObject.parseObject(willComeAgainOptionString));
        checkboxOptions.add(JSONObject.parseObject(outpatientCheckboxOptionString4));
    }

    @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);
        List<SatisfiedBody> list;
        if (inquiry.getVisitType() == VisitType.INPATIENT) {
            list = dao.selectAllInpatientSatisfiedBodies(wrapper);
        } else {
            list = dao.selectAllOutpatientSatisfiedBodies(wrapper);
        }
        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.getVisitType() == VisitType.EMERGENCY) {
            wrapper.eq("jz_flag", 1);
        } else if (inquiry.getVisitType() == VisitType.OUTPATIENT) {
            wrapper.eq("jz_flag", 0);
        }
        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.INPATIENT ?
                    " 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.INPATIENT) {
            list.forEach(item -> {
                item.setItem1(combineAnswerAndOptions(item.getItem1(), item.getItem2(), 2, item.getItem2Input()));
                item.setItem3(combineAnswerAndOptions(item.getItem3(), item.getItem4(), 3, item.getItem4Input()));
                item.setItem5(combineAnswerAndOptions(item.getItem5(), item.getItem6(), 4, item.getItem6Input()));
                item.setItem7(combineAnswerAndOptions(item.getItem7(), item.getItem8(), 5, item.getItem8Input()));
                item.setItem9(combineAnswerAndOptions(item.getItem9(), item.getItem10(), 3, item.getItem10Input()));
                item.setItem11(combineAnswerAndOptions(item.getItem11(), item.getItem12(), 3, item.getItem12Input()));
                item.setItem13(combineAnswerAndOptions(item.getItem13(), item.getItem14(), 0, item.getItem14Input()));
                item.setItem15(combineAnswerAndOptions(item.getItem15(), item.getItem16(), 0, item.getItem16Input()));
                item.setItem17(combineAnswerAndOptions(item.getItem17(), item.getItem18(), 0, item.getItem18Input()));
                item.setItem19(combineAnswerAndOptions(item.getItem19(), item.getItem20(), 0, item.getItem20Input()));
                item.setItem21(combineAnswerAndOptions(item.getItem21(), item.getItem22(), 0, item.getItem22Input()));
                item.setItem23(combineAnswerAndOptions(item.getItem23(), item.getItem24(), 9, item.getItem24Input()));
                item.setItem1002(analyzedCheckboxOptions(item.getItem1002(), 7, item.getItem1002Input()));
                item.setItem1004(analyzedCheckboxOptions(item.getItem1004(), 8, null));
            });
        } else {
            list.forEach(item -> {
                item.setItem1(combineAnswerAndOptions(item.getItem1(), item.getItem2(), 0, item.getItem2Input()));
                item.setItem3(combineAnswerAndOptions(item.getItem3(), item.getItem4(), 0, item.getItem4Input()));
                item.setItem5(combineAnswerAndOptions(item.getItem5(), item.getItem6(), 0, item.getItem6Input()));
                item.setItem7(combineAnswerAndOptions(item.getItem7(), item.getItem8(), 0, item.getItem8Input()));
                item.setItem9(combineAnswerAndOptions(item.getItem9(), item.getItem10(), 0, item.getItem10Input()));
                item.setItem11(combineAnswerAndOptions(item.getItem11(), item.getItem12(), 6, item.getItem12Input()));
                item.setItem13(combineAnswerAndOptions(item.getItem13(), item.getItem14(), 1, item.getItem14Input()));
                item.setItem15(combineAnswerAndOptions(item.getItem15(), item.getItem16(), 9, item.getItem16Input()));
                item.setItem1002(analyzedCheckboxOptions(item.getItem1002(), 7, item.getItem1002Input()));
                item.setItem1004(analyzedCheckboxOptions(item.getItem1004(), 8, null));
            });
        }
    }

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

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

    public PatientBriefInfo getPatientBriefInfo(String patNo, Integer times) {
        if (times == 0) {
            return dao.selectOutpatientBriefInfo(patNo);
        }
        PatientBriefInfo info = dao.selectInpatientBriefInfo("zy_inactpatient", patNo, times);
        if (null == info) {
            info = dao.selectInpatientBriefInfo("zy_actpatient", patNo, times);
        }
        return info;
    }

    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) {
        inquiry.setDeleted(0);
        QueryWrapper<?> wrapper = makeQueryWrapper(inquiry);
        AnalyzeResult result = new AnalyzeResult();
        VisitType visitType = inquiry.getVisitType();
        List<BriefSuggestion> suggestions;
        if (visitType == VisitType.INPATIENT) {
            suggestions = dao.selectInpatientSuggestions(wrapper);
        } else {
            suggestions = dao.selectOutpatientSuggestions(wrapper);
        }
        result.setSuggestions(suggestions);
        String table = visitType == VisitType.INPATIENT ?
                "t_inpatient_satisfied_assessment" : "t_clinic_satisfied_assessment";
        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 mjzdzhlAssessmentCount = 0;
        int mjzdzhlUnsatisfiedCount = 0;
        int mjzysAssessmentCount = 0;
        int mjzysUnsatisfiedCount = 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 ybkAssessmentCount = 0;
        int ybkUnsatisfiedCount = 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 mzyhAssessmentCount = 0;
        int mzyhUnsatisfiedCount = 0;
        int jzyhAssessmentCount = 0;
        int jzyhUnsatisfiedCount = 0;
        // -->

        int mjzdzhlCheckedOptionsCount = 0;
        JSONObject mjzdzhlOptionsJson = JSONObject.parseObject("{\"A\": 0,\"B\": 0,\"C\": 0,\"D\": 0,\"E\": 0,\"F\": 0}");
        int mjzysCheckedOptionsCount = 0;
        JSONObject mjzysOptionsJson = JSONObject.parseObject("{\"A\": 0,\"B\": 0,\"C\": 0,\"D\": 0,\"E\": 0,\"F\": 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 ybkCheckedOptionsCount = 0;
        JSONObject ybkOptionsJson = 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}");
        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 whyComeHereOptionsCount = 0;
        JSONObject whyComeHereOptionsJson = JSONObject.parseObject("{\"A\": 0,\"B\": 0,\"C\": 0,\"D\": 0,\"E\": 0,\"F\": 0,\"G\": 0}");
        int willComeAgainOptionsCount = 0;
        JSONObject willComeAgainOptionsJson = JSONObject.parseObject("{\"A\": 0,\"B\": 0,\"C\": 0}");
        int[] gradeNumDetails = new int[] {0,0,0,0,0,0,0,0,0,0};
        int gradeSum = 0;
        for (SatisfiedBody body : list) {
            if (StringUtil.notBlank(body.getItem1002())) {
                whyComeHereOptionsCount = getCheckedOptionsCount(whyComeHereOptionsCount,
                        whyComeHereOptionsJson, body.getItem1002());
            }
            if (StringUtil.notBlank(body.getItem1004())) {
                willComeAgainOptionsCount = getCheckedOptionsCount(willComeAgainOptionsCount,
                        willComeAgainOptionsJson, body.getItem1004());
            }

            if (null != body.getItem1006()) {
                int grade = body.getItem1006();
                gradeSum += grade;
                gradeNumDetails[grade - 1] = gradeNumDetails[grade - 1] + 1;
            }

            if (StringUtil.notBlank(body.getItem1()) && !body.getItem1().equals("C")) {
                totalOptionCount += 1;
                if (visitType == VisitType.INPATIENT) {
                    hlryAssessmentCount += 1;
                } else {
                    yjkAssessmentCount += 1;
                }
            }
            if (Objects.equals("B", body.getItem1())) {
                totalUnsatisfiedOptionCount += 1;
                if (visitType == VisitType.INPATIENT) {
                    hlryUnsatisfiedCount += 1;
                    hlryCheckedOptionsCount = getCheckedOptionsCount(hlryCheckedOptionsCount, hlryOptionsJson, body.getItem2());
                } else {
                    yjkUnsatisfiedCount += 1;
                    yjkCheckedOptionsCount = getCheckedOptionsCount(yjkCheckedOptionsCount, yjkOptionsJson, body.getItem2());
                }
            }
            if (StringUtil.notBlank(body.getItem3()) && !body.getItem3().equals("C")) {
                totalOptionCount += 1;
                if (visitType == VisitType.INPATIENT) {
                    ksysAssessmentCount += 1;
                } else {
                    fskAssessmentCount += 1;
                }
            }
            if (Objects.equals("B", body.getItem3())) {
                totalUnsatisfiedOptionCount += 1;
                if (visitType == VisitType.INPATIENT) {
                    ksysUnsatisfiedCount += 1;
                    ksysCheckedOptionsCount = getCheckedOptionsCount(ksysCheckedOptionsCount, ksysOptionsJson, body.getItem4());
                } else {
                    fskUnsatisfiedCount += 1;
                    fskCheckedOptionsCount = getCheckedOptionsCount(fskCheckedOptionsCount, fskOptionsJson, body.getItem4());
                }
            }
            if (StringUtil.notBlank(body.getItem5()) && !body.getItem5().equals("C")) {
                totalOptionCount += 1;
                if (visitType == VisitType.INPATIENT) {
                    hjwsAssessmentCount += 1;
                } else {
                    csyxkAssessmentCount += 1;
                }
            }
            if (Objects.equals("B", body.getItem5())) {
                totalUnsatisfiedOptionCount += 1;
                if (visitType == VisitType.INPATIENT) {
                    hjwsUnsatisfiedCount += 1;
                    hjwsCheckedOptionsCount = getCheckedOptionsCount(hjwsCheckedOptionsCount, hjwsOptionsJson, body.getItem6());
                } else {
                    csyxkUnsatisfiedCount += 1;
                    csyxkCheckedOptionsCount = getCheckedOptionsCount(csyxkCheckedOptionsCount, csyxkOptionsJson, body.getItem6());
                }
            }
            if (StringUtil.notBlank(body.getItem7()) && !body.getItem7().equals("C")) {
                totalOptionCount += 1;
                if (visitType == VisitType.INPATIENT) {
                    stAssessmentCount += 1;
                } else {
                    jykAssessmentCount += 1;
                }
            }
            if (Objects.equals("B", body.getItem7())) {
                totalUnsatisfiedOptionCount += 1;
                if (visitType == VisitType.INPATIENT) {
                    stUnsatisfiedCount += 1;
                    stCheckedOptionsCount = getCheckedOptionsCount(stCheckedOptionsCount, stOptionsJson, body.getItem8());
                } else {
                    jykUnsatisfiedCount += 1;
                    jykCheckedOptionsCount = getCheckedOptionsCount(jykCheckedOptionsCount, jykOptionsJson, body.getItem8());
                }
            }
            if (StringUtil.notBlank(body.getItem9()) && !body.getItem9().equals("C")) {
                totalOptionCount += 1;
                if (visitType == VisitType.INPATIENT) {
                    yjkAssessmentCount += 1;
                } else {
                    sfckAssessmentCount += 1;
                }
            }
            if (Objects.equals("B", body.getItem9())) {
                totalUnsatisfiedOptionCount += 1;
                if (visitType == VisitType.INPATIENT) {
                    yjkUnsatisfiedCount += 1;
                    yjkCheckedOptionsCount = getCheckedOptionsCount(yjkCheckedOptionsCount, yjkOptionsJson, body.getItem10());
                } else {
                    sfckUnsatisfiedCount += 1;
                    sfckCheckedOptionsCount = getCheckedOptionsCount(sfckCheckedOptionsCount, sfckOptionsJson, body.getItem10());
                }
            }

            if (StringUtil.notBlank(body.getItem11()) && !body.getItem11().equals("C")) {
                totalOptionCount += 1;
                if (visitType == VisitType.INPATIENT) {
                    fskAssessmentCount += 1;
                } else {
                    mjzdzhlAssessmentCount += 1;
                }
            }
            if (Objects.equals("B", body.getItem11())) {
                totalUnsatisfiedOptionCount += 1;
                if (visitType == VisitType.INPATIENT) {
                    fskUnsatisfiedCount += 1;
                    fskCheckedOptionsCount = getCheckedOptionsCount(fskCheckedOptionsCount, fskOptionsJson, body.getItem12());
                } else {
                    mjzdzhlUnsatisfiedCount += 1;
                    mjzdzhlCheckedOptionsCount = getCheckedOptionsCount(mjzdzhlCheckedOptionsCount, mjzdzhlOptionsJson, body.getItem12());
                }
            }

            if (StringUtil.notBlank(body.getItem13()) && !body.getItem13().equals("C")) {
                totalOptionCount += 1;
                if (visitType == VisitType.INPATIENT) {
                    csyxkAssessmentCount += 1;
                } else {
                    mjzysAssessmentCount += 1;
                }
            }
            if (Objects.equals("B", body.getItem13())) {
                totalUnsatisfiedOptionCount += 1;
                if (visitType == VisitType.INPATIENT) {
                    csyxkUnsatisfiedCount += 1;
                    csyxkCheckedOptionsCount = getCheckedOptionsCount(csyxkCheckedOptionsCount, csyxkOptionsJson, body.getItem14());
                } else {
                    mjzysUnsatisfiedCount += 1;
                    mjzysCheckedOptionsCount = getCheckedOptionsCount(mjzysCheckedOptionsCount, mjzysOptionsJson, body.getItem14());
                }
            }

            if (StringUtil.notBlank(body.getItem15()) && !body.getItem15().equals("C")) {
                totalOptionCount += 1;
                if (visitType == VisitType.INPATIENT) {
                    jykAssessmentCount += 1;
                } else {
                    ybkAssessmentCount += 1;
                }
            }
            if (Objects.equals("B", body.getItem15())) {
                totalUnsatisfiedOptionCount += 1;
                if (visitType == VisitType.INPATIENT) {
                    jykUnsatisfiedCount += 1;
                    jykCheckedOptionsCount = getCheckedOptionsCount(jykCheckedOptionsCount, jykOptionsJson, body.getItem16());
                } else {
                    ybkUnsatisfiedCount += 1;
                    ybkCheckedOptionsCount = getCheckedOptionsCount(ybkCheckedOptionsCount, ybkOptionsJson, body.getItem16());
                }
            }

            if (visitType == VisitType.INPATIENT) {
                if (StringUtil.notBlank(body.getItem17()) && !body.getItem17().equals("C")) {
                    totalOptionCount += 1;
                    sfckAssessmentCount += 1;
                }
                if (Objects.equals("B", body.getItem17())) {
                    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.getItem19())) {
                    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.getItem21())) {
                    totalUnsatisfiedOptionCount += 1;
                    jzyhUnsatisfiedCount += 1;
                    jzyhCheckedOptionsCount = getCheckedOptionsCount(jzyhCheckedOptionsCount, jzyhOptionsJson, body.getItem22());
                }
                if (StringUtil.notBlank(body.getItem23()) && !body.getItem23().equals("C")) {
                    totalOptionCount += 1;
                    ybkAssessmentCount += 1;
                }
                if (Objects.equals("B", body.getItem23())) {
                    totalUnsatisfiedOptionCount += 1;
                    ybkUnsatisfiedCount += 1;
                    ybkCheckedOptionsCount = getCheckedOptionsCount(ybkCheckedOptionsCount, ybkOptionsJson, body.getItem24());
                }
            }
        }
        result.setTotalOptionCount(totalOptionCount);
        result.setTotalUnsatisfiedOptionCount(totalUnsatisfiedOptionCount);
        result.setTotalUnsatisfiedOptionPercentage(makePercentage(totalUnsatisfiedOptionCount, totalOptionCount));

        result.setMjzdzhlAssessmentCount(mjzdzhlAssessmentCount);
        result.setMjzysAssessmentCount(mjzysAssessmentCount);
        result.setYjkAssessmentCount(yjkAssessmentCount);
        result.setFskAssessmentCount(fskAssessmentCount);
        result.setCsyxkAssessmentCount(csyxkAssessmentCount);
        result.setJykAssessmentCount(jykAssessmentCount);
        result.setSfckAssessmentCount(sfckAssessmentCount);
        result.setYbkAssessmentCount(ybkAssessmentCount);
        // <-- 以下住院独有
        result.setHlryAssessmentCount(hlryAssessmentCount);
        result.setKsysAssessmentCount(ksysAssessmentCount);
        result.setHjwsAssessmentCount(hjwsAssessmentCount);
        result.setStAssessmentCount(stAssessmentCount);
        result.setMzyhAssessmentCount(mzyhAssessmentCount);
        result.setJzyhAssessmentCount(jzyhAssessmentCount);
        // -->

        result.setMjzdzhlUnsatisfiedCount(mjzdzhlUnsatisfiedCount);
        result.setMjzysUnsatisfiedCount(mjzysUnsatisfiedCount);
        result.setYjkUnsatisfiedCount(yjkUnsatisfiedCount);
        result.setFskUnsatisfiedCount(fskUnsatisfiedCount);
        result.setCsyxkUnsatisfiedCount(csyxkUnsatisfiedCount);
        result.setJykUnsatisfiedCount(jykUnsatisfiedCount);
        result.setSfckUnsatisfiedCount(sfckUnsatisfiedCount);
        result.setYbkUnsatisfiedCount(ybkUnsatisfiedCount);
        // <-- 以下住院独有
        result.setHlryUnsatisfiedCount(hlryUnsatisfiedCount);
        result.setKsysUnsatisfiedCount(ksysUnsatisfiedCount);
        result.setHjwsUnsatisfiedCount(hjwsUnsatisfiedCount);
        result.setStUnsatisfiedCount(stUnsatisfiedCount);
        result.setMzyhUnsatisfiedCount(mzyhUnsatisfiedCount);
        result.setJzyhUnsatisfiedCount(jzyhUnsatisfiedCount);
        // -->

        result.setMjzdzhlUnsatisfiedPercentage(makePercentage(mjzdzhlUnsatisfiedCount, mjzdzhlAssessmentCount));
        result.setMjzysUnsatisfiedPercentage(makePercentage(mjzysUnsatisfiedCount, mjzysAssessmentCount));
        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.setYbkUnsatisfiedPercentage(makePercentage(ybkUnsatisfiedCount, ybkAssessmentCount));
        // <-- 以下住院独有
        result.setHlryUnsatisfiedPercentage(makePercentage(hlryUnsatisfiedCount, hlryAssessmentCount));
        result.setKsysUnsatisfiedPercentage(makePercentage(ksysUnsatisfiedCount, ksysAssessmentCount));
        result.setHjwsUnsatisfiedPercentage(makePercentage(hjwsUnsatisfiedCount, hjwsAssessmentCount));
        result.setStUnsatisfiedPercentage(makePercentage(stUnsatisfiedCount, stAssessmentCount));
        result.setMzyhUnsatisfiedPercentage(makePercentage(mzyhUnsatisfiedCount, mzyhAssessmentCount));
        result.setJzyhUnsatisfiedPercentage(makePercentage(jzyhUnsatisfiedCount, jzyhAssessmentCount));
        // -->

        result.setMjzdzhlUnsatisfiedOption(fillOptionDetails(mjzdzhlAssessmentCount, mjzdzhlCheckedOptionsCount, mjzdzhlOptionsJson, 6));
        result.setMjzysUnsatisfiedOption(fillOptionDetails(mjzysAssessmentCount, mjzysCheckedOptionsCount, mjzysOptionsJson, 1));
        result.setYjkUnsatisfiedOption(fillOptionDetails(yjkAssessmentCount, yjkCheckedOptionsCount, yjkOptionsJson, 0));
        result.setFskUnsatisfiedOption(fillOptionDetails(fskAssessmentCount, fskCheckedOptionsCount, fskOptionsJson, visitType == VisitType.INPATIENT ? 3 : 0));
        result.setCsyxkUnsatisfiedOption(fillOptionDetails(csyxkAssessmentCount, csyxkCheckedOptionsCount, csyxkOptionsJson, 0));
        result.setJykUnsatisfiedOption(fillOptionDetails(jykAssessmentCount, jykCheckedOptionsCount, jykOptionsJson, 0));
        result.setSfckUnsatisfiedOption(fillOptionDetails(sfckAssessmentCount, sfckCheckedOptionsCount, sfckOptionsJson, 0));
        result.setYbkUnsatisfiedOption(fillOptionDetails(ybkAssessmentCount, ybkCheckedOptionsCount, ybkOptionsJson, 9));

        // <-- 以下住院独有
        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));
        result.setMzyhUnsatisfiedOption(fillOptionDetails(mzyhAssessmentCount, mzyhCheckedOptionsCount, mzyhOptionsJson, visitType == VisitType.INPATIENT ? 0 : 1));
        result.setJzyhUnsatisfiedOption(fillOptionDetails(jzyhAssessmentCount, jzyhCheckedOptionsCount, jzyhOptionsJson, 0));
        // -->

        WhyChooseHere why = new WhyChooseHere();
        WillComeAgain will = new WillComeAgain();
        GradeNum grade = new GradeNum();

        why.setTotalCount(whyComeHereOptionsCount);
        why.setMmelCount(whyComeHereOptionsJson.getInteger("A"));
        why.setJjxzCount(whyComeHereOptionsJson.getInteger("B"));
        why.setPytjCount(whyComeHereOptionsJson.getInteger("C"));
        why.setWlcxCount(whyComeHereOptionsJson.getInteger("D"));
        why.setFwspCount(whyComeHereOptionsJson.getInteger("E"));
        why.setHjsbCount(whyComeHereOptionsJson.getInteger("F"));
        why.setYljgCount(whyComeHereOptionsJson.getInteger("G"));

        why.setMmelPercentage(makePercentage(why.getMmelCount(), whyComeHereOptionsCount));
        why.setJjxzPercentage(makePercentage(why.getJjxzCount(), whyComeHereOptionsCount));
        why.setPytjPercentage(makePercentage(why.getPytjCount(), whyComeHereOptionsCount));
        why.setWlcxPercentage(makePercentage(why.getWlcxCount(), whyComeHereOptionsCount));
        why.setFwspPercentage(makePercentage(why.getFwspCount(), whyComeHereOptionsCount));
        why.setHjsbPercentage(makePercentage(why.getHjsbCount(), whyComeHereOptionsCount));
        why.setYljgPercentage(makePercentage(why.getYljgCount(), whyComeHereOptionsCount));

        will.setTotalCount(willComeAgainOptionsCount);
        will.setYesCount(willComeAgainOptionsJson.getInteger("A"));
        will.setNoCount(willComeAgainOptionsJson.getInteger("B"));
        will.setBydCount(willComeAgainOptionsJson.getInteger("C"));

        will.setYesPercentage(makePercentage(will.getYesCount(), willComeAgainOptionsCount));
        will.setNoPercentage(makePercentage(will.getNoCount(), willComeAgainOptionsCount));
        will.setBydPercentage(makePercentage(will.getBydCount(), willComeAgainOptionsCount));

        int gradeCount = 0;
        for (int item : gradeNumDetails) {
            gradeCount += item;
        }
        grade.setTotalCount(gradeCount);
        grade.setOneCount(gradeNumDetails[0]);
        grade.setTwoCount(gradeNumDetails[1]);
        grade.setThreeCount(gradeNumDetails[2]);
        grade.setFourCount(gradeNumDetails[3]);
        grade.setFiveCount(gradeNumDetails[4]);
        grade.setSixCount(gradeNumDetails[5]);
        grade.setSevenCount(gradeNumDetails[6]);
        grade.setEightCount(gradeNumDetails[7]);
        grade.setNineCount(gradeNumDetails[8]);
        grade.setTenCount(gradeNumDetails[9]);
        grade.setAverageGrade(DecimalUtil.divide(new BigDecimal(gradeSum), new BigDecimal(gradeCount), 2));

        grade.setOnePercentage(makePercentage(grade.getOneCount(), gradeCount));
        grade.setTwoPercentage(makePercentage(grade.getTwoCount(), gradeCount));
        grade.setThreePercentage(makePercentage(grade.getThreeCount(), gradeCount));
        grade.setFourPercentage(makePercentage(grade.getFourCount(), gradeCount));
        grade.setFivePercentage(makePercentage(grade.getFiveCount(), gradeCount));
        grade.setSixPercentage(makePercentage(grade.getSixCount(), gradeCount));
        grade.setSevenPercentage(makePercentage(grade.getSevenCount(), gradeCount));
        grade.setEightPercentage(makePercentage(grade.getEightCount(), gradeCount));
        grade.setNinePercentage(makePercentage(grade.getNineCount(), gradeCount));
        grade.setTenPercentage(makePercentage(grade.getTenCount(), gradeCount));

        result.setWhyChooseHere(why);
        result.setWillComeAgain(will);
        result.setGradeNum(grade);

        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 || checkboxOptionIndex == 6) {
            unsatisfiedOption.setJsspCount(optionsJson.getInteger("A"));
            unsatisfiedOption.setJsspPercentage(makePercentage(unsatisfiedOption.getJsspCount(), checkedOptionSize));
            unsatisfiedOption.setYsbhCount(optionsJson.getInteger("B"));
            unsatisfiedOption.setYsbhPercentage(makePercentage(unsatisfiedOption.getYsbhCount(), checkedOptionSize));

            if (checkboxOptionIndex != 6) {
                unsatisfiedOption.setQtCount(optionsJson.getInteger("G"));
                unsatisfiedOption.setQtPercentage(makePercentage(unsatisfiedOption.getQtCount(), checkedOptionSize));
            }
            if (checkboxOptionIndex == 2 || checkboxOptionIndex == 6) {
                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));
        } else if (checkboxOptionIndex == 9) {
            unsatisfiedOption.setZynlCount(optionsJson.getInteger("A"));
            unsatisfiedOption.setZynlPercentage(makePercentage(unsatisfiedOption.getZynlCount(), checkedOptionSize));
            unsatisfiedOption.setDdscCount(optionsJson.getInteger("B"));
            unsatisfiedOption.setDdscPercentage(makePercentage(unsatisfiedOption.getDdscCount(), checkedOptionSize));
            unsatisfiedOption.setJsxyCount(optionsJson.getInteger("E"));
            unsatisfiedOption.setJsxyPercentage(makePercentage(unsatisfiedOption.getJsxyCount(), checkedOptionSize));
            unsatisfiedOption.setFwlcCount(optionsJson.getInteger("G"));
            unsatisfiedOption.setFwlcPercentage(makePercentage(unsatisfiedOption.getFwlcCount(), 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) + 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 + "%";
    }
}
