package com.ywt.outpatient.service.rpc;


import com.ywt.biz.common.util.CacheUtil;
import com.ywt.biz.common.util.Checker;
import com.ywt.biz.common.util.StringHelper;
import com.ywt.gapi.ResultCode;
import com.ywt.gapi.system.*;
import com.ywt.outpatient.core.SqlHelper;
import com.ywt.outpatient.core.utils.CollectionUtil;
import com.ywt.outpatient.domain.entity.center.Hospital;
import com.ywt.outpatient.domain.entity.center.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

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

@Service
@Scope("singleton")
public class HospitalService {
    private static Logger logger = LoggerFactory.getLogger(UserService.class);

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

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

    // 获取医生头衔列表缓存键
    private final String DOCTOR_TITLE_LIST = "DoctorTitleList";

    @Autowired
    private HospitalRepository hospitalRepository;

    @Autowired
    private DepartmentRepository departmentRepository;

    @Autowired
    private SqlHelper sqlHelperYwtcenter;

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Autowired
    private DoctorTitleRepository doctorTitleRepository;

    public List<Hospital> getHospitalList() {
        return hospitalRepository.getHospitalList();
    }

    /**
     * 从数据库返回所有部门数据
     *
     * @return
     */
    public List<Department> getDepartmentList() {
        try {
            return departmentRepository.findAll();
        } catch (Exception e) {
        }
        return new LinkedList<>();
    }

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

    /**
     * 从缓存中返回所有医院 Map by ID
     *
     * @return
     */
    public Map<Integer, Hospital> getHospitalMap() {
        try {
            return (Map<Integer, Hospital>) CacheUtil.getInstance().get(HOSPITAL_MAP, new Callable<Object>() {
                @Override
                public Object call() throws Exception {
                    Map<Integer, Hospital> mapTemp = CollectionUtil.toMap(getHospitalListHigh(), p -> p.getId());
                    if (mapTemp == null) {
                        return new HashMap<>();
                    }
                    return mapTemp;
                }
            });
        } catch (Exception e) {
        }
        return new HashMap<>();
    }

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

    /**
     * 从缓存中返回所有部门数据 Map by ID
     *
     * @return
     */
    public Map<Integer, Department> getDepartmentMap() {
        try {
            return (Map<Integer, Department>) CacheUtil.getInstance().get(DEPARTMENT_MAP, new Callable<Object>() {
                @Override
                public Object call() throws Exception {
                    Map<Integer, Department> mapTemp = CollectionUtil.toMap(getDepartmentListHigh(), p -> p.getId());
                    if (mapTemp == null) {
                        return new HashMap<>();
                    }
                    return mapTemp;
                }
            });
        } catch (Exception e) {
        }
        return new HashMap<>();
    }

    public List<Hospital> getHospitalListByIds(String hospitalIds) {
        List<Hospital> lst = new LinkedList<>();

        if (StringHelper.isNullOrWhiteSpace(hospitalIds)) {
            return lst;
        }

        String[] strHospitalIds = hospitalIds.split(",");

        for (String strHospitalId : strHospitalIds) {
            if (StringHelper.isNullOrEmpty(strHospitalId)) {
                continue;
            }

            int hospitalId = Checker.parseInt(strHospitalId);
            Hospital hospital = getHospital(hospitalId);

            if (hospital != null) {
                lst.add(hospital);
            }
        }

        return lst;
    }

    public Hospital getHospital(int hospitalId) {
        if (hospitalId > 0) {
            Map<Integer, Hospital> hospitalMap = getHospitalMap();

            if (hospitalMap.containsKey(hospitalId)) {
                return hospitalMap.get(hospitalId);
            }
        }
        return null;
    }

    public List<Department> getDepartmentListByIds(String deptIds) {
        List<Department> lst = new LinkedList<>();

        if (StringHelper.isNullOrWhiteSpace(deptIds)) {
            return lst;
        }

        String[] strHospitalIds = deptIds.split(",");

        for (String strDeptId : strHospitalIds) {
            if (StringHelper.isNullOrEmpty(strDeptId)) {
                continue;
            }

            int deptId = Checker.parseInt(strDeptId);
            Department dept = getDepartment(deptId);

            if (dept != null) {
                lst.add(dept);
            }
        }

        return lst;
    }

    public Department getDepartment(int deptId) {
        if (deptId > 0) {
            Map<Integer, Department> departmentMap = getDepartmentMap();

            if (departmentMap.containsKey(deptId)) {
                return departmentMap.get(deptId);
            }
        }
        return null;
    }

    public Hospital findHospitalById(int id) {
        return hospitalRepository.findById(id).orElse(null);
    }

    public List<Department> findDepartmentListByHospitalId(int hospitalId) {
        // 兼容传过来的医院为子医院的情况，如果hospitalId=0，只查hospital_id为0的数据，如果大于0，则需要考虑到sub_hospital_id
        if (hospitalId == 0) {
            List<Department> departmentList = getDepartmentListHigh().stream().filter(p -> p.getHospitalId().equals(hospitalId)).collect(Collectors.toList());
            departmentList = departmentList.stream().sorted(Comparator.comparing(Department::getWeight).reversed()).collect(Collectors.toList());
            return departmentList;
//            Select * From department Where hospital_id = ? and is_deleted = 0 order by weight desc;
//            return departmentRepository.findByHospitalId(hospitalId);
        } else {
            List<Department> departmentList = getDepartmentListHigh().stream().filter(p -> (p.getHospitalId().equals(hospitalId) || p.getSubHospitalId().equals(hospitalId))).collect(Collectors.toList());
            departmentList = departmentList.stream().sorted(Comparator.comparing(Department::getWeight).reversed()).collect(Collectors.toList());
            return departmentList;
            // Select * From department Where (hospital_id = ? or sub_hospital_id = ?) and is_deleted = 0 order by weight desc;
            //return departmentRepository.findByHospitalId(hospitalId, hospitalId);
        }
    }

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

    public Department getDepartmentBydepartemtId(int departemtId) {
        return departmentRepository.findById(departemtId).orElse(null);
    }

    /**
     * 根据地区获取医院列表
     *
     * @param areaIds
     * @return
     */
    public List<Hospital> getHospitalList(String areaIds) {
//        String sql = String.format("select * from hospital where status = 0 and is_deleted = 0 and area_ids like '%s' order by weight desc;", areaIds);
//        sql = "select * from hospital where status = 0 and is_deleted = 0 and area_ids like '%,900000,%' order by weight desc;";
//        return jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Hospital.class));
        return hospitalRepository.getAreaHospitalList(areaIds);
    }

    /**
     * 根据科室Ids得到科室名称
     *
     * @param deptIds
     * @return
     */
    public String getDeptNamesByDeptIds(String deptIds) {
        String deptNames = "";
        if (!Checker.isNone(deptIds)) {
            String[] deptIdstr = deptIds.split(",");
            for (String deptId : deptIdstr) {
                if (!Checker.isNone(deptId)) {
                    //科室id
//                    Department department = departmentRepository.findById(Integer.parseInt(deptId));

                    //从缓存读取 2018-08-29 14:01
                    Department department = getDepartment(Integer.parseInt(deptId));
                    if (!Checker.isNone(department) && !department.isDeleted()) {
                        deptNames += department.getName() + ",";
                    }
                }
            }
            if (!Checker.isNone(deptNames)) {
                deptNames = deptNames.substring(0, deptNames.length() - 1);
            }
        }
        return deptNames;
    }

    /**
     * 根据医院Ids得到医院名称
     *
     * @param hospitalIds
     * @return
     */
    public String getHospitalNamesByHospitalIds(String hospitalIds) {
        String hospitalNames = "";
        if (!Checker.isNone(hospitalIds)) {
            String[] hospitalIdstr = hospitalIds.split(",");
            for (String hospitalId : hospitalIdstr) {
                if (!Checker.isNone(hospitalId)) {
                    //医院id
//                    Hospital hospital = hospitalRepository.findById(Integer.parseInt(hospitalId));

                    //从缓存读取 2018-08-29 14:02
                    Hospital hospital = getHospital(Integer.parseInt(hospitalId));
                    if (!Checker.isNone(hospital) && !hospital.isDeleted()) {
                        hospitalNames += hospital.getName() + ",";
                    }
                }
            }
            if (!Checker.isNone(hospitalNames)) {
                hospitalNames = hospitalNames.substring(0, hospitalNames.length() - 1);
            }
        }
        return hospitalNames;
    }

    public String getHospitalNamesByHospitalId(int hospitalId) {
        Hospital h = getHospital(hospitalId);
        return h == null ? "" : Checker.getStringValue(h.getName());
    }


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

        }
        return new ArrayList<>();
    }


    public List<DoctorTitle> getDoctorTitleListHigh() {
        try {
            return (List<DoctorTitle>) CacheUtil.getInstance().get(DOCTOR_TITLE_LIST, () -> getDoctorTitleList());
        } catch (Exception e) {

        }
        return new ArrayList<>();
    }

    public List<DoctorTitle> getDoctorTitleListByType(int type) {
        return doctorTitleRepository.getAllByDeletedFalseAndTypeOrderByWeightDesc(type);
    }

    public List<Department> findDepartmentListByHospitalId(int hospitalId, int subHospitalId) {
        // todo：这里更改成从缓存拿科室数据
        List<Department> departmentList = getDepartmentListHigh().stream().filter(p -> p.getHospitalId().equals(hospitalId) && p.getSubHospitalId().equals(subHospitalId)).collect(Collectors.toList());
        departmentList = departmentList.stream().sorted(Comparator.comparing(Department::getWeight).reversed()).collect(Collectors.toList());
        return departmentList;
//        Select * From department Where hospital_id = ? and sub_hospital_id = ? and is_deleted = 0 order by weight desc;
//        return departmentRepository.findByHospitalIdAndSubHospitalId(hospitalId, subHospitalId);
    }


    public GetHospitalByHospitalIdsResponse getHospitalByHospitalIds(GetHospitalByHospitalIdsRequest request) {
        List<Integer> hospitalIds = request.getHospitalIdList();
        List<com.ywt.gapi.system.Hospital> backHospitals = new ArrayList<>();
        GetHospitalByHospitalIdsResponse.Builder response = GetHospitalByHospitalIdsResponse.newBuilder()
                .setCode(ResultCode.SUCCEED_VALUE).setMessage("处理成功");
        if (Checker.isNone(hospitalIds)) {
            return response.setCode(ResultCode.PARAMETER_ERROR_VALUE).setMessage("参数不能为空").build();
        }
        List<Hospital> hospitalList = getHospitalListByHospitalIds(hospitalIds);
        if (!Checker.isNone(hospitalList)) {
            for (Hospital h : hospitalList) {
                com.ywt.gapi.system.Hospital hospital = com.ywt.gapi.system.Hospital.newBuilder()
                        .setHospitalId(h.getId())
                        .setHospitalName(h.getName())
                        .setLogo(h.getLogo())
                        .setAddress(h.getAddress())
                        .setParentId(h.getParentId())
                        .build();
                backHospitals.add(hospital);
            }
        }
        return response.addAllHospital(backHospitals).build();
    }

    private List<Hospital> getHospitalListByHospitalIds(List<Integer> hospitalIds) {
        if (!Checker.isNone(hospitalIds)) {
            StringBuilder builder = new StringBuilder("select * from hospital where status = 0 and is_deleted = 0 ");
            builder.append(" and ( 1=2 ");
            for (Integer hospitalId : hospitalIds) {
                builder.append(" or id =  ").append(hospitalId).append(" or parent_id = ").append(hospitalId);
            }
            builder.append(" ) order by weight desc, id desc ; ");
            return jdbcTemplate.query(builder.toString(), new BeanPropertyRowMapper<>(Hospital.class));
        }
        return null;
    }

    public List<Department> findDepartmentListByHospitalIdAndDeptName(int hospitalId, String deptName) {
        deptName = new StringBuilder()
                .append("%")
                .append(deptName.trim())
                .append("%").toString();
        return departmentRepository.findByHospitalIdAndDeptName(hospitalId, hospitalId, deptName);
    }


    public SearchDeptListByNameResponse searchDeptListByName(SearchDeptListByNameRequest request) {
        int hospitalId = request.getHospitalId();
        String deptName = request.getDeptName();
        SearchDeptListByNameResponse.Builder response = SearchDeptListByNameResponse.newBuilder()
                .setCode(ResultCode.SUCCEED_VALUE).setInfo("处理成功");
        if (hospitalId <= 0 || Checker.isNull(deptName)) {
            response.setCode(ResultCode.PARAMETER_ERROR_VALUE).setInfo("参数有误");
            return response.build();
        }
        List<Dept> returnDeptList = new ArrayList<>();
        List<Department> deptList = findDepartmentListByHospitalIdAndDeptName(hospitalId, deptName);
        if (!Checker.isNone(deptList)) {
            for (Department d : deptList) {
                Dept dept = Dept.newBuilder()
                        .setDeptId(d.getId())
                        .setDeptName(d.getName())
                        .setDeptCode(Checker.getStringValue(d.getCode()))
                        .setParentId(Checker.getIntegerValue(d.getParentId()))
                        .build();
                returnDeptList.add(dept);
            }
        }
        response.addAllDept(returnDeptList);
        return response.build();
    }

    public int getFirstIdByIds(String ids) {
        try {
            if (!Checker.isNone(ids)) {
                String[] idArr = ids.split(",");
                if (!Checker.isNone(idArr)) {
                    for (String idStr : idArr) {
                        if (!Checker.isNone(idStr)) {
                            return Integer.parseInt(idStr);
                        }
                    }
                }
            }
        } catch (Exception e) {
            logger.error("getFirstIdByIds({}):{}", ids, e.getMessage(), e);
        }
        return 0;
    }

    public String getDepartmentNameBydepartemtId(int deptId) {
        Department d = getDepartment(deptId);
        return d == null ? "" : Checker.getStringValue(d.getName());
    }
}
