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

import com.google.common.collect.Lists;
import com.yihu.wlyy.entity.doctor.profile.Doctor;
import com.yihu.wlyy.entity.doctor.team.admin.AdminTeam;
import com.yihu.wlyy.entity.doctor.team.admin.AdminTeamMember;
import com.yihu.wlyy.entity.organization.Hospital;
import com.yihu.wlyy.entity.patient.Patient;
import com.yihu.wlyy.entity.patient.SignFamily;
import com.yihu.wlyy.entity.patient.SignFamilyRenew;
import com.yihu.wlyy.repository.doctor.DoctorAdminTeamDao;
import com.yihu.wlyy.repository.doctor.DoctorAdminTeamMemberDao;
import com.yihu.wlyy.repository.doctor.DoctorDao;
import com.yihu.wlyy.repository.doctor.DoctorTeamMemberDao;
import com.yihu.wlyy.repository.organization.HospitalDao;
import com.yihu.wlyy.repository.patient.SignFamilyDao;
import com.yihu.wlyy.repository.patient.SignFamilyRenewDao;
import com.yihu.wlyy.service.BaseService;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.*;

/**
 * 医生行政团队服务。
 *
 * @author Sand
 */
@Component
@Transactional
public class AdminTeamService extends BaseService {
    @Autowired
    DoctorDao doctorDao;

    @Autowired
    DoctorAdminTeamDao teamDao;

    @Autowired
    DoctorAdminTeamMemberDao memberDao;

    @Autowired
    DoctorTeamMemberDao signingTeamMemberDao;

    @Autowired
    SignFamilyDao signFamilyDao;
    @Autowired
    SignFamilyRenewDao signFamliyRenewDao;
    @Autowired
    HospitalDao hospitalDao;
    @Autowired
    JdbcTemplate jdbcTemplate;

    /**
     * 根据医生code返回所有团队的医生
     * （pc端im使用）
     * @param doctor
     * @return
     */
    public JSONArray getTeamMembersByDoctorCode(String doctor){
        String sql = "SELECT " +
                "   d.code" +
                "   ,d.name" +
                "   ,d.hospital" +
                "   ,d.hospital_name hospitalName" +
                "   ,d.dept_name deptName" +
                "   ,d.job_name jobName" +
                "   ,d.level" +
                "   ,d.sex" +
                "   ,d.photo" +
                "   ,d.expertise" +
                "   ,d.introduce" +
                "   ,t.id teamCode" +
                " FROM " +
                "   wlyy_admin_team_member m" +
                "   , wlyy_admin_team t" +
                "   , wlyy_doctor d" +
                "   ,(SELECT t1.id FROM wlyy_admin_team_member m1, wlyy_admin_team t1 WHERE m1.doctor_code = '"+doctor+"' AND t1.id = m1.team_id AND t1.available = true AND m1.available = true) te" +
                " WHERE " +
                "   t.id = m.team_id AND " +
                "   m.doctor_code = d.code AND " +
                "   t.id = te.id AND " +
                "   t.available = true AND " +
                "   m.available = true ";
        List<Map<String, Object>> doctors = jdbcTemplate.queryForList(sql);
        Map<String, JSONObject> result = new HashMap<>();
        if(doctors!=null&&doctors.size()>0){
            for (Map<String, Object> map:doctors){
                String code = map.get("code").toString();
                if(result.containsKey(code)){
                    JSONObject json = result.get(code);
                    JSONArray ja = json.getJSONArray("teams");
                    ja.put(map.get("teamCode"));
                }else {
                    JSONObject json = new JSONObject();
                    json.put("code",map.get("code"));
                    json.put("name",map.get("name"));
                    json.put("hospital",map.get("hospital"));
                    json.put("jobName",map.get("jobName"));
                    json.put("level",map.get("level"));
                    json.put("sex",map.get("sex"));
                    json.put("photo",map.get("photo"));
                    json.put("hospitalName",map.get("hospitalName"));
                    json.put("deptName",map.get("deptName"));
                    json.put("expertise",map.get("expertise"));
                    json.put("introduce",map.get("introduce"));
                    JSONArray ja = new JSONArray();
                    ja.put(map.get("teamCode"));
                    json.put("teams",ja);
                    result.put(code,json);
                }
            }
        }

        if (result.size() > 0) {
            List<JSONObject> list = Lists.newArrayList(result.values());
            return new JSONArray(list);
        } else {
            return new JSONArray();
        }
    }

    /**
     * 获取团队数量。
     *
     * @return
     */
    public long getTeamCount() {
        return teamDao.count();
    }

    /**
     * 创建团队。
     *
     * @param teamName
     * @param leaderCode
     * @param orgCode
     * @return
     */
    public AdminTeam createTeam(String teamName, String leaderCode, String orgCode) {
        AdminTeam team = new AdminTeam();
        team.setName(teamName);
        team.setLeaderCode(leaderCode);
        team.setOrgCode(orgCode);
        team.setAvailable(true);
        team.setCreateTime(new Date());

        saveTeam(team);

        return team;
    }

    public void deleteTeam(long teamId) {
        teamDao.delete(teamId);
    }

    /**
     * 获取团队信息。
     *
     * @param id
     */
    public AdminTeam getTeam(long id) {
        AdminTeam team = teamDao.findOne(id);
        return team;
    }

    public Map<String, Object> getPatientSigningTeam(String patientCode, String currentDoctor) {

        List<Object> results = teamDao.findAdminTeamByPatientSignTeam(patientCode, new PageRequest(0, 1));
        Object[] result = (Object[]) results.get(0);
        Map<String, Object> team = new HashMap<>();
        team.put("teamId", result[0]);
        team.put("teamName", result[1]);
        team.put("isLeader", currentDoctor != null && result[2].equals(currentDoctor));
        team.put("doctorCode", result[3]);
        team.put("doctorName", result[4]);
        team.put("healthDoctorCode", result[5] == null ? "" : result[5]);
        team.put("healthDoctorName", result[6] == null ? "" : result[6]);

        return team;
    }

    /**
     * 更新团队名称。
     *
     * @param teamId
     * @param teamName
     * @return
     */
    public AdminTeam updateTeamName(long teamId, String teamName) {
        AdminTeam team = getTeam(teamId);
        if (team != null) {
            if (teamName != null) team.setName(teamName);

            saveTeam(team);
        }

        return team;
    }

    /**
     * 更新团队领导。
     *
     * @param teamId
     * @param doctorCode
     * @return
     */
    public AdminTeam updateTeamLeader(long teamId, String doctorCode) {
        AdminTeam team = getTeam(teamId);
        if (team != null) {
            if (doctorCode != null) team.setLeaderCode(doctorCode);

            saveTeam(team);
        }

        return team;
    }

    /**
     * 获取此医生所在的团队列表。
     *
     * @param doctorCode
     * @return
     */
    public List<AdminTeam> getDoctorTeams(String doctorCode) {
        return memberDao.findDoctorTeams(doctorCode);
    }

    /**
     * 添加成员。
     *
     * @param teamId
     * @param doctorCode
     */
    public void addMember(long teamId, String doctorCode) {
        if (!memberDao.isMemberExist(teamId, doctorCode)) {
            AdminTeamMember member = new AdminTeamMember();
            member.setTeamId(teamId);
            member.setDoctorCode(doctorCode);
            member.setJoinTime(new Date());
            saveMember(member);
        }
    }

    /**
     * 移除成员逻辑：
     * 1、判断团队内是否有三师签约关系，如果有不能删除。
     * 2、若没有三师签约关系，判断是否为专科医生，如果是，直接删除
     * 3、若不是，则判断健康管理师或全科医生是否有签约人，有的话提示先转移居民。
     *
     * @param teamId
     * @param doctorCode
     */
    public Pair<Integer, String> removeMember(long teamId, String doctorCode) {
        /*if (signingTeamMemberDao.isSanShiSigning(doctorCode)) {
            return new ImmutablePair<>(403, "三师签约医生，不能删除");
        }

        Doctor doctor = doctorDao.findByCode(doctorCode);
        if (!doctor.isProfessionalDoctor()) {
            if (doctor.isGeneralDoctor()) {
                List<Doctor> doctorList = new ArrayList<>();
                doctorList.add(doctor);

                Integer count = getMemberSigningCount(teamId, doctorList).get(doctorCode);
                if (count != null || count > 0) {
                    if (doctor.isGeneralDoctor()) {
                        return new ImmutablePair<>(403, "全科医生有签约关系，不可删除");
                    } else if (doctor.isHealthDoctor()) {
                        return new ImmutablePair<>(403, "健康管理师仍有签约居民，请先转移签约居民");
                    }
                }
            }
        }*/

        AdminTeamMember member = memberDao.findByTeamIdAndDoctorCodeOrderByDoctorCodeAsc(teamId, doctorCode);
        if (member != null) memberDao.removeMember(teamId, doctorCode);

        return new ImmutablePair<>(200, "OK");
    }

    public List<Doctor> getMembers(long teamId) {
        return memberDao.findAllMembers(teamId);
    }

    public List<Doctor> getMembers(long teamId, String doctorCode) {
        return memberDao.findAllHeathExcludeThis(teamId, doctorCode);
    }

    /**
     * 获取不在当前团队内的机构成员。
     *
     * @param orgCode
     * @param teamId
     * @param page
     * @param size
     * @return
     */
    public List<Doctor> getExcludedMembers(String orgCode, String doctorName, long teamId, int page, int size) {
        Pageable pageable = new PageRequest(page, size);
        if (StringUtils.isEmpty(doctorName)) {
            doctorName = "%";
        } else {
            doctorName = "%" + doctorName + "%";
        }

        Page<Doctor> doctors = memberDao.findTeamExcludedMembers(orgCode, doctorName, teamId, pageable);
        if (doctors == null) return null;

        return doctors.getContent();
    }

    /**
     * 团队内所有成员的签约人数。
     *
     * @param doctors
     * @return
     */
    public Map<String, Integer> getMemberSigningCount(long teamId, List<Doctor> doctors) {
        Map<String, Integer> counts = new HashMap<>();

        for (Doctor doctor : doctors) {
            if (doctor.isProfessionalDoctor()) continue;

            Integer signingCount;
            if (doctor.isHealthDoctor()) {
                signingCount = teamDao.getHealthDoctorSignCount(doctor.getCode(), teamId);
            } else {
                signingCount = teamDao.getDoctorSignCount(doctor.getCode(), teamId);
            }

            counts.put(doctor.getCode(), signingCount);
        }

        return counts;
    }

    /**
     * 团队内所有成员的签约患者列表。以健康管理师为中心，与全科医生为准的交集。
     *
     * @param teamId
     * @param healthDoctorCode
     * @param page
     * @param size
     * @return
     */
    public List<Patient> getMemberSigningPatients(long teamId, String healthDoctorCode, int page, int size) {
        if (page == 0 && size == 0) {
            List<Patient> result = teamDao.getHealthDoctorSigningPatients(healthDoctorCode, teamId);
            return result;
        } else {
            Page<Patient> result = teamDao.getHealthDoctorSigningPatients(healthDoctorCode, teamId, new PageRequest(page, size));
            return result.getContent();
        }
    }

    /**
     * 保存团队。
     *
     * @param team
     */
    private void saveTeam(AdminTeam team) {
        teamDao.save(team);
    }

    /**
     * 保存成员。
     *
     * @param member
     */
    private void saveMember(AdminTeamMember member) {
        memberDao.save(member);
    }

    public AdminTeam findByLeaderCode(String leaderCode) {
        return teamDao.findByLeaderCode(leaderCode);
    }


    /**
     * 查询两个医生的共同团队
     *
     * @param doctorOne
     * @param doctorTwo
     * @return
     */
    public List<AdminTeam> findDoctorsTeams(String doctorOne, String doctorTwo) {
        List<AdminTeam> teams = memberDao.findDoctorTeams(doctorOne);
        List<AdminTeam> teamsTogether = new ArrayList<>();

        if (teams != null && teams.size() > 0) {
            for (AdminTeam team : teams) {
                if (memberDao.findByTeamIdAndDoctorCodeOrderByDoctorCodeAsc(team.getId(), doctorTwo) != null) {
                    teamsTogether.add(team);
                }
            }
        }

        return teamsTogether;
    }

    /**
     * 查询居民与医生的签约团队
     *
     * @param patient 居民
     * @param doctor  医生
     * @return
     */
    public JSONArray findPatientDoctorTeam(String patient, String doctor) {
        JSONArray result = new JSONArray();
        SignFamily ssSign = signFamilyDao.findSignByPatient(patient, 1);
        SignFamily jtSign = signFamilyDao.findSignByPatient(patient, 2);
        if (ssSign != null&&ssSign.getAdminTeamId()!=null && (doctor.equals(ssSign.getDoctor())
                || doctor.equals(ssSign.getDoctorHealth()))) {
            AdminTeam team = getTeam(ssSign.getAdminTeamId());
            result.put(new JSONObject(team));
        }
        if (jtSign.getAdminTeamId()!=null&&jtSign != null && (doctor.equals(jtSign.getDoctor())
                || doctor.equals(jtSign.getDoctorHealth()))) {
            AdminTeam team = getTeam(jtSign.getAdminTeamId());
            if(ssSign == null || ssSign.getAdminTeamId() != jtSign.getAdminTeamId()) {
                result.put(new JSONObject(team));
            }
        }
        return result;
    }

    /**
     * 查询居民与医生的签约团队
     *
     * @param patient 居民
     * @param doctor  医生
     * @return
     */
    public JSONArray findRenewPatientDoctorTeam(String patient, String doctor) {
        JSONArray result = new JSONArray();
        SignFamilyRenew jtSign = signFamliyRenewDao.findSignByPatient(patient, 2);
        if (jtSign.getAdminTeamId()!=null&&jtSign != null && (doctor.equals(jtSign.getDoctor())
                || doctor.equals(jtSign.getDoctorHealth()))) {
            AdminTeam team = getTeam(jtSign.getAdminTeamId());
            result.put(new JSONObject(team));

        }
        return result;
    }

    /**
     * 查询机构下团队
     *
     * @param hospital
     * @return
     */
    public List<AdminTeam> findHospitalTeams(String hospital){
        return teamDao.findByOrgCode(hospital);
    }

    /**
     *判断该医生是否属于患者的签约行政团队
     * @param patient 患者
     * @param doctorCode 医生
     * @return
     */
    public List<AdminTeamMember> findByAdminTeam(String patient,String doctorCode){
        return memberDao.findByAdminTeam(patient,doctorCode);
    }


    public JSONObject getTeamInfo(Integer teamId){
        AdminTeam adminTeam = this.getTeam(teamId);
        JSONObject result = new JSONObject();
        JSONObject teamInfo = new JSONObject(adminTeam);
        Doctor doctor = doctorDao.findByCode(adminTeam.getLeaderCode());
        teamInfo.put("leaderName",doctor.getName());
        Hospital hospital =hospitalDao.findByCode(adminTeam.getOrgCode());
        teamInfo.put("hospitalName",hospital.getName());
        result.put("team",teamInfo);
        List<Doctor> members = memberDao.findAllMembers(teamId);
        List<JSONObject> doctors = new ArrayList<>();
        for(Doctor d:members){
            JSONObject doctorInfo = new JSONObject();
            doctorInfo.put("name",d.getName());
            doctorInfo.put("code",d.getCode());
            doctors.add(doctorInfo);
        }
        result.put("members",doctors);
        return result;
    }
}
