
package com.yihu.wlyy.service.app.consult;


import com.yihu.wlyy.aop.ObserverRequired;
import com.yihu.wlyy.entity.consult.ConsultTeam;
import com.yihu.wlyy.entity.consult.Evaluate;
import com.yihu.wlyy.entity.consult.EvaluateLabel;
import com.yihu.wlyy.entity.consult.EvaluateScore;
import com.yihu.wlyy.repository.consult.ConsultTeamDoctorDao;
import com.yihu.wlyy.repository.consult.EvaluateDao;
import com.yihu.wlyy.repository.consult.EvaluateScoreDao;
import com.yihu.wlyy.service.BaseService;
import com.yihu.wlyy.util.ClazzReflect;
import com.yihu.wlyy.util.ImUtill;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;


@Component
@Transactional
public class EvaluateService extends BaseService {
    @Autowired
    EvaluateDao evaluateDao;
    @Autowired
    ConsultTeamService consultTeamService;
    @Autowired
    EvaluateLabelService evaluateLabelService;
    @Autowired
    JdbcTemplate jdbcTemplate;
    @Autowired
    ConsultTeamDoctorDao consultTeamDoctorDao;
    @Autowired
    EvaluateScoreDao evaluateScoreDao;

    private void save(Map<String, List<Evaluate>> docEvaMap) {
        for (String key : docEvaMap.keySet())
            evaluateDao.save(docEvaMap.get(key));
    }

    public void saveByJson(String jsonData, String patient) {
        JSONObject jsonObject = new JSONObject(jsonData);
        String consult = jsonObject.getString("consult");
        ConsultTeam consultTeam = consultTeamService.findByCode(consult);
        //评价的分数
        JSONArray evaluateArray = jsonObject.getJSONArray("evaluate");
        //标签
        JSONArray labelArray = jsonObject.getJSONArray("label");

        JSONArray doctorArray = jsonObject.getJSONArray("doctors");

        List<Evaluate> evaluateList = null;
        List<EvaluateLabel> evaluateLabelList = new ArrayList<>();
        Map<String, List<Evaluate>> docEvaMap = new HashMap<>();
        //反射生成评价对象
        for (Object evaluateObj : evaluateArray) {
            Evaluate evaluate = new Evaluate();
            JSONObject obj = (JSONObject) evaluateObj;
            ClazzReflect clazzReflect = new ClazzReflect();
            evaluate = (Evaluate) clazzReflect.formatToClazz(evaluate, obj);
            evaluate.setConsult(consult);
            evaluate.setPatient(patient);
            //把分数放入map中 给参与此次咨询的医生都评分
            if (docEvaMap.get(evaluate.getDoctor()) == null) {
                evaluateList = new ArrayList<>();
                evaluateList.add(evaluate);
                docEvaMap.put(evaluate.getDoctor(), evaluateList);
            } else {
                docEvaMap.get(evaluate.getDoctor()).add(evaluate);
            }
        }
        //反射得到标签内容
        for (Object labelObj : labelArray) {
            EvaluateLabel evaluateLabel = new EvaluateLabel();
            JSONObject obj = (JSONObject) labelObj;
            ClazzReflect clazzReflect = new ClazzReflect();
            evaluateLabel = (EvaluateLabel) clazzReflect.formatToClazz(evaluateLabel, obj);
            evaluateLabel.setConsult(consult);
            evaluateLabel.setPatient(patient);
            evaluateLabelList.add(evaluateLabel);
        }
        Map<String,JSONObject> doctorMap = new HashMap<>();
        //生成医生信息
        for(Object doctor : doctorArray){
            JSONObject d = (JSONObject) doctor;
            doctorMap.put((String)d.get("doctor"),d);
        }

        //计算单条得分
        evaluateScoreC(docEvaMap, consult,doctorMap);
        this.save(docEvaMap);
        evaluateLabelService.save(evaluateLabelList);
        consultTeam.setEvaluate(1);
        consultTeam.setEvaluateTime(new Date());
        JSONObject topicObject = new JSONObject();
        topicObject.put("evaluate", 1);
        topicObject.put("evaluate_time", new Date());
        ImUtill.updateTopics(consult, topicObject.toString());
        this.consultTeamService.save(consultTeam);
    }

    public void updateByJson(String jsonData, String patient) {
        JSONObject jsonObject = new JSONObject(jsonData);
        String consult = jsonObject.getString("consult");
        JSONArray doctors = jsonObject.getJSONArray("doctors");

        if(doctors!=null&&doctors.length()>0){
            for(Object d:doctors){
                JSONObject jd = (JSONObject) d;
                String doctor = jd.getString("doctor");
                //删除各类别分数
                String delEvSql = " DELETE  FROM wlyy_evaluate  WHERE consult ='"+consult+"' AND doctor ='"+doctor+"'";
                //删除分数
                String delEvScoceSql ="DELETE  FROM wlyy_evaluate_score  WHERE consult ='"+consult+"' AND doctor ='"+doctor+"'";
                //删除标签
                String delEvLabelSql="DELETE  FROM wlyy_evaluate_label  WHERE consult ='"+consult+"' AND doctor ='"+doctor+"'";
                //删除旧的平均及标签
                jdbcTemplate.execute(delEvSql);
                jdbcTemplate.execute(delEvScoceSql);
                jdbcTemplate.execute(delEvLabelSql);
            }
        }
        //保存新的平均
        saveByJson(jsonData,patient);
    }

    /**
     * 查询某个咨询某种类型的评价
     *
     * @param consult
     * @param type
     * @return
     */
    public List<Evaluate> getEvaluateByConsultAndType(String consult, int type) {
        List<Evaluate> evaluates = evaluateDao.findByConsultAndType(consult, type);
        return evaluates;
    }

    /**
     * 查询某个咨询的评价
     *
     * @param consult
     * @return
     */
    public List<Evaluate> getEvaluateByConsult(String consult) {
        List<Evaluate> evaluates = evaluateDao.findByConsult(consult);
        return evaluates;
    }

    /**
     * 获取某个医生的某种类型的评价
     *
     * @param doctor
     * @param type
     * @return
     */
    public List<Evaluate> getEvaluateByDoctorAndType(String doctor, int type) {
        List<Evaluate> evaluates = evaluateDao.findByDoctorAndType(doctor, type);
        return evaluates;
    }

    private void evaluateScoreC(Map<String, List<Evaluate>> docEvaMap, String consult,Map<String,JSONObject> doctorMap) {
        for (String doctor : docEvaMap.keySet()) {
                BigDecimal anonymousScore1 = new BigDecimal(ANONYMOUS_SCORE_DEFAULT_ONE);//专业能力
                BigDecimal anonymousScore2 = new BigDecimal(ANONYMOUS_SCORE_DEFAULT_TWO);//服务态度
                BigDecimal anonymousScore3 = new BigDecimal(ANONYMOUS_SCORE_DEFAULT_THREE);//回复速度
                //计算此次评价的分数来源
                for (Evaluate evaluate : docEvaMap.get(doctor)) {
                    if (evaluate.getEvaluateType() == 1) {
                        anonymousScore1 = BigDecimal.valueOf(evaluate.getScore());
                    } else if (evaluate.getEvaluateType() == 2) {
                        anonymousScore2 = BigDecimal.valueOf(evaluate.getScore());
                    } else if (evaluate.getEvaluateType() == 3) {
                        anonymousScore3 = BigDecimal.valueOf(evaluate.getScore());
                    }
                }
                BigDecimal score = (anonymousScore1.add(anonymousScore2).add(anonymousScore3)).divide(new BigDecimal(3),1,RoundingMode.HALF_UP);
                EvaluateScore evaluateScore = new EvaluateScore();
                evaluateScore.setConsult(consult);
                evaluateScore.setDoctor(doctor);
                evaluateScore.setScore(score.doubleValue());
                //获取医生评价信息
                JSONObject doctorInfo = doctorMap.get(doctor);
                String remark = (String)doctorInfo.get("remark");
                if(StringUtils.isNotBlank(remark)){
                    evaluateScore.setRemark(remark);
                }else{
                    //如果没有评价信息,根据分数评价内容
                    if(score.compareTo(new BigDecimal(71))==0&&score.compareTo(new BigDecimal(71))==1){
                        evaluateScore.setRemark("好评");
                    }else if(score.compareTo(new BigDecimal(41))==-1){
                        evaluateScore.setRemark("差评");
                    }else{
                        evaluateScore.setRemark("中评");
                    }
                }
                evaluateScoreDao.save(evaluateScore);
        }
    }

    /**
     * 改用evaluateScoreC的平均规则
     * @param docEvaMap
     * @param consult
     */
    @Deprecated
    private void evaluateScoreCal(Map<String, List<Evaluate>> docEvaMap, String consult) {
        for (String doctor : docEvaMap.keySet()) {
            List<Evaluate> evaluates = docEvaMap.get(doctor);
            if (evaluates.size() == 1) {
                //如果一条那么这条一定是实名，只有实名那么分数按实名的来存
                EvaluateScore evaluateScore = new EvaluateScore();
                evaluateScore.setConsult(consult);
                evaluateScore.setDoctor(doctor);
                evaluateScore.setScore(Double.valueOf(evaluates.get(0).getScore()));
                evaluateScoreDao.save(evaluateScore);
            } else {
                //如果既有实名和匿名的那么按照公式来存
                BigDecimal realScore = new BigDecimal(REAL_SCORE_DEFAULT);//实名评价
                BigDecimal anonymousScore1 = new BigDecimal(ANONYMOUS_SCORE_DEFAULT_ONE);//专业能力
                BigDecimal anonymousScore2 = new BigDecimal(ANONYMOUS_SCORE_DEFAULT_TWO);//服务态度
                BigDecimal anonymousScore3 = new BigDecimal(ANONYMOUS_SCORE_DEFAULT_THREE);//回复速度
                //计算此次评价的分数来源
                for (Evaluate evaluate : docEvaMap.get(doctor)) {
                    if (evaluate.getEvaluateType() == 0) {
                        realScore = BigDecimal.valueOf(evaluate.getScore());
                    } else if (evaluate.getEvaluateType() == 1) {
                        anonymousScore1 = BigDecimal.valueOf(evaluate.getScore());
                    } else if (evaluate.getEvaluateType() == 2) {
                        anonymousScore2 = BigDecimal.valueOf(evaluate.getScore());
                    } else if (evaluate.getEvaluateType() == 3) {
                        anonymousScore3 = BigDecimal.valueOf(evaluate.getScore());
                    }
                }
                String evaluateTimesSql = "select count(1) as count from wlyy_evaluate w where w.doctor =? GROUP BY w.consult,w.doctor";
                //有效评价次数
                List<Map<String, Object>> evaluateTimesList = jdbcTemplate.queryForList(evaluateTimesSql, new Object[]{doctor});
                //有效咨询次数
                int consultTimes = consultTeamDoctorDao.countByDoctorAndType(2, doctor);
                BigDecimal score = BigDecimal.ZERO;//总分
                BigDecimal anonymousScore = BigDecimal.ZERO;//加权平均分笔直综合
                BigDecimal jiaquan = BigDecimal.ZERO;//加权平均分
                //加权平均分=（实名评分×30%+专业能力×20%+服务态度×25%+回复速度×25%）/有效评价次数
                anonymousScore = anonymousScore.add(realScore.multiply(new BigDecimal("0.3")));
                anonymousScore = anonymousScore.add(anonymousScore1.multiply(new BigDecimal("0.2")));
                anonymousScore = anonymousScore.add(anonymousScore2.multiply(new BigDecimal("0.25")));
                anonymousScore = anonymousScore.add(anonymousScore3.multiply(new BigDecimal("0.25")));
//			int evaTimes = 0;
//			if(evaluateTimesList.size()>0){
//				evaTimes = evaluateTimesList.size();
//			}else{
//				evaTimes = 1;
//			}
//			jiaquan  = anonymousScore.divide(BigDecimal.valueOf(evaTimes),2,BigDecimal.ROUND_HALF_UP);//算的加权平均分
//			//满意度=80+（加权平均分-80）/系数
//			//咨询系数 咨询次数≤100次，对应系数为3；
//			//100次<咨询次数≤1000次，对应系数为2；
//			//咨询次数>1000次，对应系数为1。
//			if (consultTimes <= 100) {  //咨询系数 咨询次数≤100次，对应系数为3；
//				//100次<咨询次数≤1000次，对应系数为2；
//				//咨询次数>1000次，对应系数为1。
//				jiaquan = (jiaquan.subtract(BigDecimal.valueOf(80L))).divide(BigDecimal.valueOf(3L),2,BigDecimal.ROUND_HALF_UP);
//			} else if (consultTimes > 100 && consultTimes <= 1000) {
//				jiaquan = (jiaquan.subtract(BigDecimal.valueOf(80L))).divide(BigDecimal.valueOf(2L),2,BigDecimal.ROUND_HALF_UP);
//			} else {
//				jiaquan = (jiaquan.subtract(BigDecimal.valueOf(80L))).divide(BigDecimal.valueOf(1L),2,BigDecimal.ROUND_HALF_UP);
//			}
//			score = jiaquan.add(BigDecimal.valueOf(80L)).setScale(1, BigDecimal.ROUND_HALF_UP);
                score = anonymousScore;
                EvaluateScore evaluateScore = new EvaluateScore();
                evaluateScore.setConsult(consult);
                evaluateScore.setDoctor(doctor);
                evaluateScore.setScore(score.doubleValue());
                evaluateScoreDao.save(evaluateScore);
            }
        }
    }

    public JSONArray getDoctorSorceList(String doctor,String type,Integer page,Integer size){

        String sql = "SELECT " +
                " (case e.type WHEN 2 then '匿名' ELSE p.`name` END) `name`,  " +
                " TIMESTAMPDIFF(YEAR,p.birthday,SYSDATE()) age,s.consult,s.score,e.type,  " +
                " max(case e.evaluate_type when 1 then e.score else 0 end) ability,  " +
                " max(case e.evaluate_type when 2 then e.score else 0 end) attitude,  " +
                " max(case e.evaluate_type when 3 then e.score else 0 end) speed  " +
                " FROM wlyy_evaluate_score s  " +
                " ,wlyy_evaluate e  " +
                " ,wlyy_consult_team c " +
                " ,wlyy_patient p  " +
                " WHERE s.consult = e.consult " +
                " AND s.consult = c.consult   " +
                " AND p.`code` = c.patient " +
                " AND e.evaluate_type <> 0  "+
                " AND s.doctor ='"+doctor+"' ";


        if("0".equals(type)){
            //全部
        }else if("1".equals(type)){
            //好评
            sql = sql +" AND s.score >=71 ";
        }else if("2".equals(type)){
            //中评
            sql = sql +" AND s.score >=41 AND s.score <71 ";
        }else if("3".equals(type)){
            //差评
            sql = sql +" AND s.score <41 ";
        }

        if(page!=null&&size!=null){
            page = page -1;
            sql = sql+ " GROUP BY s.consult LIMIT "+page*size+","+size+" ";
        }else{
            sql = sql=" GROUP BY s.consult ";
        }

        List<Map<String,Object>> rs = jdbcTemplate.queryForList(sql);
        return new JSONArray(rs);
    }

    public JSONArray getScoreListTitle(String doctor){
        String sql ="SELECT  " +
                " (SELECT COUNT(1) FROM wlyy_evaluate_score s " +
                " WHERE s.doctor='"+doctor+"') total,  " +
                " (SELECT COUNT(1) FROM wlyy_evaluate_score s " +
                " WHERE s.doctor='"+doctor+"' AND s.score>=71) good, " +
                " (SELECT COUNT(1) FROM wlyy_evaluate_score s " +
                " WHERE  s.doctor='"+doctor+"' AND s.score>=41 AND s.score<71) notBad, " +
                " (SELECT COUNT(1) FROM wlyy_evaluate_score s " +
                " WHERE  s.doctor='"+doctor+"' AND s.score<41) bad";
        List<Map<String,Object>> rs = jdbcTemplate.queryForList(sql);
        return new JSONArray(rs);
    }

    public JSONArray getScoreTitle(String doctor){
        String sql = "SELECT" +
                " (SELECT evaluate_score FROM wlyy_doctor WHERE code ='"+doctor+"') score ," +
                " (SELECT ifnull(FORMAT(avg(score),1),0)  FROM wlyy_evaluate  WHERE evaluate_type = 1 AND doctor ='"+doctor+"') ability ," +
                " (SELECT ifnull(FORMAT(avg(score),1),0)  FROM wlyy_evaluate  WHERE evaluate_type = 2 AND doctor ='"+doctor+"') attitude ," +
                " (SELECT ifnull(FORMAT(avg(score),1),0)  FROM wlyy_evaluate  WHERE evaluate_type = 3 AND doctor ='"+doctor+"') speed";
        List<Map<String,Object>> rs =jdbcTemplate.queryForList(sql);
        return new JSONArray(rs);
    }

    public static Long REAL_SCORE_DEFAULT = 100L;
    public static Long ANONYMOUS_SCORE_DEFAULT_ONE = 100L;
    public static Long ANONYMOUS_SCORE_DEFAULT_TWO = 100L;
    public static Long ANONYMOUS_SCORE_DEFAULT_THREE = 100L;
}
