package com.ywt.mg.services;

import com.ywt.gapi.user.DoctorInfo;
import com.ywt.mg.core.PagedList;
import com.ywt.mg.core.SqlHelper;
import com.ywt.mg.core.structs.TrieTree;
import com.ywt.mg.core.utils.CacheUtil;
import com.ywt.mg.core.utils.Checker;
import com.ywt.mg.core.utils.CollectionUtil;
import com.ywt.mg.core.utils.serializers.JsonSerializer;
import com.ywt.mg.domain.entities.*;
import com.ywt.mg.domain.models.DoctorInfoLess;
import com.ywt.mg.domain.models.HospitalInfoLess;
import com.ywt.mg.web.common.DoctorSrv;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class HospitalCacheService {

    private static Logger logger = LoggerFactory.getLogger(HospitalCacheService.class);

    private final String HOSPITAL_LIST = "HospitalList";
    private final String HOSPITAL_MAP = "HospitalMap";
    private final String HOSPITAL_INFO_LESS_TRIE = "HospitalInfoLessTrie";

    private final String DEPARTMENT_LIST = "DepartmentList";
    private final String DEPARTMENT_MAP = "DepartmentMap";

    private final String DOCTOR_TITLE_LIST = "DoctorTitleList";
    private final String DOCTOR_INFO_LESS_TRIE = "DoctorInfoLessTrie";

    @Autowired
    private DoctorSrv doctorSrv;

    @Autowired
    private HospitalRepository hospitalRepository;

    @Autowired
    private DepartmentRepository departmentRepository;

    @Autowired
    private SqlHelper sqlHelperYwtcenter;

    @Autowired
    private DoctorTitleRepository doctorTitleRepository;

    /**
     * 得到的是所有未删除的医院
     *
     * @return
     */
    public List<Hospital> getHospitalList() {
        try {
            return hospitalRepository.findAllHospital();
        } catch (Exception e) {
            logger.error("HospitalCacheService#getHospitalList():\n {}", e.getMessage(), e);
        }
        return new LinkedList<>();
    }

    /**
     * 从数据库返回所有部门数据
     *
     * @return
     */
    public List<Department> getDepartmentList() {
        try {
            return departmentRepository.findAll();
        } catch (Exception e) {
            logger.error("HospitalCacheService#getDepartmentList():\n {}", e.getMessage(), e);
        }
        return new LinkedList<>();
    }

    /**
     * 从缓存中返回所有医院
     *
     * @return
     */
    public List<Hospital> getHospitalListHigh() {
        try {
            return (List<Hospital>) CacheUtil.getInstance().get(HOSPITAL_LIST, () -> getHospitalList());
        } catch (Exception e) {
            logger.error("HospitalCacheService#getHospitalListHigh():\n {}", e.getMessage(), e);
        }
        return new LinkedList<>();
    }

    /**
     * 从缓存中返回所有医院 Map by ID
     *
     * @return
     */
    public Map<Integer, Hospital> getHospitalMap() {
        try {
            return (Map<Integer, Hospital>) CacheUtil.getInstance().get(HOSPITAL_MAP, () ->  CollectionUtil.toMap(getHospitalListHigh(), Hospital::getId));
        } catch (Exception e) {
            logger.error("HospitalCacheService#getHospitalMap():\n {}", e.getMessage(), e);
        }
        return new HashMap<>();
    }

    /**
     * 从缓存中返回所有部门数据
     *
     * @return
     */
    public List<Department> getDepartmentListHigh() {
        try {
            return (List<Department>) CacheUtil.getInstance().get(DEPARTMENT_LIST, () -> getDepartmentList());
        } catch (Exception e) {
            logger.error("HospitalCacheService#getDepartmentListHigh():\n {}", e.getMessage(), e);
        }
        return new LinkedList<>();
    }

    /**
     * 从缓存中返回所有部门数据 Map by ID
     *
     * @return
     */
    public Map<Integer, Department> getDepartmentMap() {
        try {
            return (Map<Integer, Department>) CacheUtil.getInstance().get(DEPARTMENT_MAP, ()->  CollectionUtil.toMap(getDepartmentListHigh(),Department::getId));
        } catch (Exception e) {
            logger.error("HospitalCacheService#getDepartmentMap():\n {}", e.getMessage(), e);
        }
        return new HashMap<>();
    }

    private TrieTree<HospitalInfoLess> getHospitalTrieTreeData() {
        TrieTree<HospitalInfoLess> trieTree = new TrieTree<HospitalInfoLess>();
        getHospitalListHigh().forEach(p -> {
            HospitalInfoLess hospitalInfoLess = new HospitalInfoLess();
            hospitalInfoLess.setId(p.getId());
            hospitalInfoLess.setName(p.getName());
            hospitalInfoLess.setCode(p.getCode());
            trieTree.insert(p.getName(), hospitalInfoLess);
        });
        return trieTree;
    }
    /**
     * 生成医院前缀树
     *
     * @return
     */
    public TrieTree<HospitalInfoLess> getHospitalTrieTree() {
        try {
            return (TrieTree<HospitalInfoLess>) CacheUtil.getInstance().get(HOSPITAL_INFO_LESS_TRIE, () -> getHospitalTrieTreeData());
        } catch (Exception e) {
            logger.error("HospitalCacheService#getHospitalTrieTree():\n {}", e.getMessage(), e);
        }
        return new TrieTree<HospitalInfoLess>();
    }

    public Hospital findHospitalById(int id) {
        return hospitalRepository.findOne(id);
    }

    public List<Department> findDepartmentListByHospitalId(int hospitalId) {
        return departmentRepository.findByHospitalId(hospitalId);
    }

    public List<Department> findAllByHospitalId(int hospitalId) {
        return departmentRepository.findAllByHospitalId(hospitalId);
    }


    public String test() {
        PagedList<Department> list = sqlHelperYwtcenter.getPagedList(1, 5, "id, parent_id", "hospital_id=? and name_first_letter=?", null, Department.class, new Object[]{1, "Z"});

        String rtn = JsonSerializer.toJson(list);
        return rtn;
    }

    public Department getDepartmentBydepartemtId(int departemtId) {
        return departmentRepository.findOne(departemtId);
    }

    /**
     * 通过医生的HospitalIds得到所有对应的医院名称
     *
     * @param hospitalIds
     * @return
     */
    public String getHospitalNameByHospitalIds(String hospitalIds) {
        StringBuffer hospitalName = new StringBuffer();
        if (!Checker.isNull(hospitalIds)) {
            String[] ids = hospitalIds.split(",");
            for (String id : ids) {
                if (Checker.isNumeric(id)) {
                    Hospital hospital = getHospitalMap().getOrDefault(Integer.parseInt(id), null);
                    if (!Checker.isNone(hospital)) {
                        hospitalName.append(hospital.getName() + ",");
                    }
                }
            }
        }
        String hospitalname = hospitalName.toString();
        if (!Checker.isNone(hospitalname))
            hospitalname = hospitalname.substring(0, hospitalname.length() - 1);
        return hospitalname;
    }

    public String getCacheHospitalNameByHospitalId(int hospitalId) {
        Hospital hospital = getHospitalMap().getOrDefault(hospitalId, null);
        if (!Checker.isNone(hospital)){
            return hospital.getName();
        }
        return "";
    }

    /**
     * 通过医生的deptIds得到所有对应的科室名称
     *
     * @param deptIds
     * @return
     */
    public String getDepartmentByDeptIds(String deptIds) {
        StringBuffer deptName = new StringBuffer();
        if (!Checker.isNull(deptIds)) {
            String[] ids = deptIds.split(",");
            for (String id : ids) {
                if (Checker.isNumeric(id)) {
                    Department department = getDepartmentMap().getOrDefault(Integer.parseInt(id), null);
                    if (!Checker.isNone(department)) {
                        deptName.append(department.getName() + ",");
                    }
                }
            }
        }
        String deptname = deptName.toString();
        if (!Checker.isNone(deptname))
            deptname = deptname.substring(0, deptname.length() - 1);
        return deptname;
    }

    public List<DoctorTitle> getDoctorTitleList(){
        try {
            return doctorTitleRepository.findAll();
        }catch (Exception e){

        }
        return new ArrayList<>();
    }


    public List<DoctorTitle> getDoctorTitleListHigh(int type){
        try {
            List<DoctorTitle> list = (List<DoctorTitle>) CacheUtil.getInstance().get(DOCTOR_TITLE_LIST, () -> getDoctorTitleList());
            if (!Checker.isNone(list))
                return list.stream().filter(p->p.getType()==type).collect(Collectors.toList());
        }catch (Exception e){
            logger.error("HospitalCacheService#getDoctorTitleListHigh():\n {}", e.getMessage(), e);

        }
        return doctorTitleRepository.findAllByType(type);
    }

    private TrieTree<DoctorInfoLess> getDoctorTrieTreeData() {
        TrieTree<DoctorInfoLess> trieTree = new TrieTree<DoctorInfoLess>();
        List<DoctorInfo> infoList = doctorSrv.getDoctorAll();
        if (!Checker.isNone(infoList)) {
            infoList.forEach(p -> {
                DoctorInfoLess doctorInfoLess = new DoctorInfoLess();
                doctorInfoLess.setId(p.getDoctorid());
                doctorInfoLess.setName(p.getName());
                doctorInfoLess.setMobile(p.getMobile());
                doctorInfoLess.setHospitalName(p.getHospital());
                doctorInfoLess.setDeptName(p.getDept());
                doctorInfoLess.setHospitalIds(p.getHospitalIds());
                // todo: 姓名可能会有重复的，所以后面加上手机号，则唯一
                trieTree.insert(p.getName().concat(p.getMobile()), doctorInfoLess);
            });
        }
        return trieTree;
    }
    /**
     * 生成医生信息前缀树
     *
     * @return {@link TrieTree <DoctorInfoLess>}
     */
    public TrieTree<DoctorInfoLess> getDoctorTrieTree() {
        try {
            return  (TrieTree<DoctorInfoLess>) CacheUtil.getInstance().get(DOCTOR_INFO_LESS_TRIE, () -> getDoctorTrieTreeData());
        } catch (Exception e) {
            logger.error("HospitalCacheService#getDoctorTrieTree():\n {}", e.getMessage(), e);
        }
        return new TrieTree<DoctorInfoLess>();
    }

    /**
     * 通过hospitalId 和 deptCode得到Department
     *
     * @param hospitalId 医院ID
     * @param deptCode 科室编号
     * @return {@link Department}
     */
    public Department getDepartmentByHospitalIdAndDeptCode(int hospitalId, String deptCode) {
        if (hospitalId == 0 || Checker.isNull(deptCode)) {
            return null;
        }
        List<Department> departmentList = getDepartmentListHigh();
        Department department = departmentList.stream().filter(p-> hospitalId == p.getHospitalId() && deptCode.equals(p.getCode())).findFirst().orElse(null);
        return department;
    }

    /**
     * 通过hospitalId 和 deptCode得到科室名称
     *
     * @param hospitalId 医院ID
     * @param deptCode 科室编号
     * @return {@link Department}
     */
    public String getDepartmentNameByHospitalIdAndDeptCode(int hospitalId, String deptCode) {
        Department department = getDepartmentByHospitalIdAndDeptCode(hospitalId, deptCode);
        if (department == null){
            return "";
        }
        return department.getName();
    }

    /**
     * 根据医院ID得到缓存中的医院信息
     * @param hospitalId 医院ID
     * @return {@link Hospital}
     */
    public Hospital getCacheHospitalByHospitalId(int hospitalId) {
        return getHospitalMap().getOrDefault(hospitalId, null);
    }

    public int getFirstHospitalId(String hospitalIds) {
        return getFirstId(hospitalIds);
    }


    public int getFirstDeptId(String deptIds) {
        return getFirstId(deptIds);
    }

    public int getFirstId(String ids) {
        if (Checker.isNone(ids)) {
            return 0;
        }
        String[] idArr = ids.split(",");
        for (String id : idArr) {
            if (!Checker.isNone(id)) {
                return Integer.parseInt(id);
            }
        }
        return 0;
    }

    /**
     * 根据科室ID得到缓存中的科室信息
     * @param deptId 科室ID
     * @return {@link Department}
     */
    public Department getCacheDepartmentByDeptId(int deptId) {
        return getDepartmentMap().getOrDefault(deptId, null);
    }

    /**
     * 根据科室ID得到缓存中的科室信息
     * @param deptId 科室ID
     * @return {@link Department}
     */
    public String getCacheDepartmentNameByDeptId(int deptId) {
        Department department = getDepartmentMap().getOrDefault(deptId, null);
        if (department != null){
            return department.getName();
        }
        return "";
    }
}
