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

import com.yihu.wlyy.entity.device.Device;
import com.yihu.wlyy.entity.device.PatientBloodSugger;
import com.yihu.wlyy.entity.device.PatientDevice;
import com.yihu.wlyy.entity.device.PatientHealthTime;
import com.yihu.wlyy.entity.doctor.profile.Doctor;
import com.yihu.wlyy.entity.doctor.team.admin.AdminTeam;
import com.yihu.wlyy.entity.patient.Patient;
import com.yihu.wlyy.repository.deviece.DeviceDao;
import com.yihu.wlyy.repository.deviece.PatientBloodSuggerDao;
import com.yihu.wlyy.repository.deviece.PatientHealthTimeDao;
import com.yihu.wlyy.repository.doctor.DoctorAdminTeamMemberDao;
import com.yihu.wlyy.repository.doctor.DoctorDao;
import com.yihu.wlyy.repository.patient.PatientDao;
import com.yihu.wlyy.repository.patient.PatientDeviceDao;
import com.yihu.wlyy.service.BaseService;
import com.yihu.wlyy.service.app.team.AdminTeamService;
import com.yihu.wlyy.util.DateUtil;
import com.yihu.wlyy.util.HttpClientUtil;
import com.yihu.wlyy.util.SystemConf;
import org.apache.commons.lang3.StringUtils;
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.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springside.modules.persistence.DynamicSpecifications;
import org.springside.modules.persistence.SearchFilter;
import org.springside.modules.persistence.SearchFilter.Operator;
import org.springside.modules.utils.Clock;

import java.util.*;

@Component
@Transactional(rollbackFor = Exception.class)
public class PatientDeviceService extends BaseService {

    private Clock clock = Clock.DEFAULT;

    @Autowired
    private DoctorDao doctorDao;

    @Autowired
    private PatientDeviceDao patientDeviceDao;

    @Autowired
    private DeviceDao deviceDao;

    @Autowired
    private PatientDao patientDao;

    @Autowired
    private DoctorAdminTeamMemberDao doctorAdminTeamMemberDao;

    @Autowired
    private AdminTeamService adminTeamService;
    @Autowired
    private PatientBloodSuggerDao patientBloodSuggerDao;
    @Autowired
    private PatientHealthTimeDao patientHealthTimeDao;

    private String url = SystemConf.getInstance().getYihuOpenPlatformUrl();
    private String appid = SystemConf.getInstance().getYihuOpenPlatformAppId();
    private String secret = SystemConf.getInstance().getYihuOpenPlatformSecret();

    private String registerDevice = "DeviceGateway/DeviceApi/registerDevice";//注册设备


    /**
     * 保存患者设备
     */
    public boolean saveDevice(PatientDevice patientDevice) throws Exception {
        synchronized (patientDevice.getDeviceSn()) {
            //判断sn码是否被使用
            String sn = patientDevice.getDeviceSn();
            String type = patientDevice.getCategoryCode();
            Long deviceId = patientDevice.getDeviceId();
            String userType = patientDevice.getUserType();
            if (userType == null) {
                userType = "-1";
                patientDevice.setUserType("-1");
            }

            boolean needVerify = true;
            //修改操作
            if (patientDevice.getId() != null) {
                PatientDevice deviceOld = patientDeviceDao.findOne(patientDevice.getId());
                if (deviceOld != null) {
                    if (deviceOld.getDeviceSn().equals(sn)) {
                        needVerify = false;
                    }
                } else {
                    throw new Exception("不存在该条记录！");
                }
            }

            //校验sn码是否被使用
            if (needVerify) {
//				PatientDevice device = patientDeviceDao.findByDeviceIdAndDeviceSnAndUserType(deviceId, sn, userType);
                PatientDevice device = patientDeviceDao.findByDeviceSnAndUserType(sn, userType);
                if (device != null && !device.getId().equals(patientDevice.getId())) {
                    throw new Exception("sn码" + sn + "已被使用！");
                }
            }
            patientDevice.setCzrq(clock.getCurrentDate());
            //当前用户的身份证
            Patient patient = patientDao.findByCode(patientDevice.getUser());
            patientDevice.setUserIdcard(patient.getIdcard());

            //注册设备
            Map<String, String> params = new HashMap<>();
            params.put("deviceSn", sn);

            //调用服务
            String response = HttpClientUtil.httpPost(url + registerDevice, HttpClientUtil.getSecretParams(params, appid, secret));
            System.out.println("注册设备=" + response);
            JSONObject json = new JSONObject(response);
            String code = json.get("Code").toString();
            //10000注册成功 10001已注册 -10000参数不通过(没传参数) -10001设备不存在 -10002设备未出库
            if ("10000".equals(code) || "10001".equals(code)) {
                patientDeviceDao.save(patientDevice);
            } else {
                String message = json.get("Message").toString();
                throw new Exception(message);
            }

            return true;
        }
    }

    /**
     * 注册设备
     *
     * @return
     * @throws Exception
     */
    public String registerSnInit() throws Exception {
        String re = "";
        Iterable<PatientDevice> iterable = patientDeviceDao.findAll();
        if (iterable != null) {
            for (PatientDevice patientDevice : iterable) {
                String deviceSn = patientDevice.getDeviceSn();
                Map<String, String> params = new HashMap<>();
                params.put("deviceSn", deviceSn);

                String response = HttpClientUtil.httpPost(url + registerDevice, HttpClientUtil.getSecretParams(params, appid, secret));
                System.out.println("注册设备=" + response);
                JSONObject json = new JSONObject(response);
                String code = json.get("Code").toString();
                //10000注册成功 10001已注册 -10000参数不通过(没传参数) -10001设备不存在 -10002设备未出库
                if ("10000".equals(code) || "10001".equals(code)) {

                } else {
                    String message = json.get("Message").toString();
                    re += deviceSn + message + ";";
                }
            }
        }
        return re;
    }

    /**
     * 单个注册
     *
     * @param deviceSn
     * @return
     * @throws Exception
     */
    public String registerSn(String deviceSn) throws Exception {
        Map<String, String> params = new HashMap<>();
        params.put("deviceSn", deviceSn);

        String response = HttpClientUtil.httpPost(url + registerDevice, HttpClientUtil.getSecretParams(params, appid, secret));
        return response;
    }


    public void deleteDevices(String deviceSn, String type, String uuid) {
        List<PatientDevice> patientDevices = patientDeviceDao.findByDeviceSnAndCategoryCode(deviceSn, type);
        if (patientDevices == null || patientDevices.size() == 0) {
            throw new RuntimeException("设备未被绑定！");
        }
        for (PatientDevice patientDevice : patientDevices) {
            patientDeviceDao.delete(patientDevice);
        }
    }


    /**
     * 删除患者设备
     */
    public List<JSONObject> deleteDevice(String id, String uuid) {
        PatientDevice device = patientDeviceDao.findOne(Long.valueOf(id));
        patientDeviceDao.delete(device);
        List<PatientDevice> patientDevices = patientDeviceDao.findByDeviceSnAndCategoryCode(device.getDeviceSn(), device.getCategoryCode());
        List<JSONObject> objects = new ArrayList<>();
        for (PatientDevice patientDevice : patientDevices) {
            JSONObject object = new JSONObject(patientDevice);
            Patient patient = patientDao.findByCode(patientDevice.getUser());
            if (patient != null) {
                object.put("userName", patient.getName());
            }
            objects.add(object);
        }
        return objects;
    }

    /**
     * 患者设备列表接口（分页）
     */
    public Page<PatientDevice> findByPatient(String patientCode, long id, int pageSize) {
        if (id < 0) {
            id = 0;
        }
        if (pageSize <= 0) {
            pageSize = 10;
        }
        // 排序
        Sort sort = new Sort(Direction.DESC, "id");
        // 分页信息
        PageRequest pageRequest = new PageRequest(0, pageSize, sort);

        // 设置查询条件
        Map<String, SearchFilter> filters = new HashMap<String, SearchFilter>();

        filters.put("patient", new SearchFilter("user", Operator.EQ, patientCode));

        //filters.put("del", new SearchFilter("del", Operator.EQ, 0));

        if (id > 0) {
            filters.put("id", new SearchFilter("id", Operator.LT, id));
        }

        Specification<PatientDevice> spec = DynamicSpecifications.bySearchFilter(filters.values(), PatientDevice.class);

        return patientDeviceDao.findAll(spec, pageRequest);
    }

    /**
     * 患者设备列表接口--医生端
     */
    public List<Map<String, Object>> findByDoctor(String patientCode, String doctorCode, int page, int pagesize) {
        List<Map<String, Object>> re = new ArrayList<>();
        if (page <= 0) {
            page = 1;
        }
        if (pagesize <= 0) {
            pagesize = 10;
        }

        //boolean bo = false;
        ////判断该医生是否属于患者的签约行政团队
        //List<AdminTeamMember> adminTeamMembers = doctorAdminTeamMemberDao.findByAdminTeam(patientCode,doctorCode);
        //if(adminTeamMembers!=null && adminTeamMembers.size()>0)
        //{
        //	bo = true;
        //}

        PageRequest pageRequest = new PageRequest(page - 1, pagesize);

        List<PatientDevice> list = new ArrayList<>();
        //if(bo) //签约医生查看所有设备
        //{
        //	list = patientDeviceDao.findByUser(patientCode,pageRequest);
        //}
        //else{
        //	list = patientDeviceDao.findByUserAndDoctor(patientCode, doctorCode,pageRequest);
        //}
        list = patientDeviceDao.findByUser(patientCode, pageRequest);
        if (list != null) {
            //获取设备路径,医生姓名
            List<Device> deviceList = deviceDao.findAll();
            Doctor self = doctorDao.findByCode(doctorCode);
            for (PatientDevice item : list) {
                Map<String, Object> map = new HashMap<>();
                if (StringUtils.isNotBlank(item.getDoctor())) {
                    if (StringUtils.equals(item.getDoctor(), doctorCode)) {
                        map.put("role", 1);//可解绑自己绑定的
                    } else {
                        List<AdminTeam> adminTeams = adminTeamService.findDoctorsTeams(item.getDoctor(), doctorCode);
                        if (adminTeams != null && adminTeams.size() > 0) {
                            map.put("role", 1);//同行政团队可解绑
                        } else {
                            map.put("role", 0);//不同行政团队不可解绑
                        }
                    }
                } else {
                    map.put("role", 0);//患者自己绑定无法解绑
                }
                map.put("id", item.getId());
                map.put("deviceId", item.getDeviceId());
                map.put("deviceSn", item.getDeviceSn());
                map.put("user", item.getUser());
                map.put("categoryCode", item.getCategoryCode());
                map.put("userType", item.getUserType());
                map.put("userIdcard", item.getUserIdcard());
                map.put("czrq", DateUtil.dateToStrLong(item.getCzrq()));
                String deviceDoctor = item.getDoctor();
                if (deviceDoctor == null) {
                    map.put("doctor", "");
                    map.put("doctorName", "");
                } else {
                    map.put("doctor", deviceDoctor);
                    if (deviceDoctor.equals(doctorCode)) {
                        map.put("doctorName", self.getName());
                    } else {
                        Doctor doctor = doctorDao.findByCode(deviceDoctor);
                        if (doctor != null) {
                            map.put("doctorName", doctor.getName());
                        } else {
                            map.put("doctorName", "");
                        }
                    }
                }


                //获取设备路径
                for (Device de : deviceList) {
                    if (de.getId().equals(item.getDeviceId())) {
                        map.put("deviceName", de.getName());
                        map.put("devicePhoto", de.getPhoto());
                        map.put("deviceBrands", de.getBrands());
                        break;
                    }
                }
                re.add(map);
            }
        }

        re.sort(new Comparator<Map<String, Object>>() {
            @Override
            public int compare(Map<String, Object> o1, Map<String, Object> o2) {
                if (o1.get("czrq").toString().compareTo(o2.get("czrq").toString()) > 0) {
                    return -1;
                }
                if (o1.get("czrq").toString().compareTo(o2.get("czrq").toString()) < 0) {
                    return 1;
                }

                return 0;
            }
        });

        return re;
    }

    /**
     * 查询患者已拥有的设备
     *
     * @param patient
     * @return
     */
    public Iterator<PatientDevice> findPatientHave(String patient) {
        return patientDeviceDao.findByUser(patient).iterator();
    }

    /**
     * 获取患者设备信息
     **/
    public PatientDevice findById(String id) {
        return patientDeviceDao.findOne(Long.valueOf(id));
    }


    /**
     * 通过sn码获取设备绑定情况
     **/
    public List<Map<String, String>> getDeviceUser(String user, String deviceSn, String type) throws Exception {
        List<Map<String, String>> re = new ArrayList<>();
        List<PatientDevice> list = patientDeviceDao.findByDeviceSnAndCategoryCode(deviceSn, type);
        if (list != null) {
            for (PatientDevice item : list) {
                Map<String, String> map = new HashMap<>();
                map.put("type", item.getUserType());
                String code = item.getUser();
                if (code.equals(user)) {
                    map.put("others", "0");
                } else {
                    map.put("others", "1");
                }

                //获取姓名
                Patient patient = patientDao.findByCode(code);
                if (patient != null) {
                    map.put("name", patient.getName());
                } else {
                    map.put("name", code);
                }

                re.add(map);
            }
        }

        return re;
    }

    public JSONArray getDeviceByDeviceSn(String deviceSn, String type) {
        List<PatientDevice> list = patientDeviceDao.findByDeviceSnAndCategoryCode(deviceSn, type);
        JSONArray objects = new JSONArray();
        for (PatientDevice patientDevice : list) {
            JSONObject object = new JSONObject(patientDevice);
            Patient patient = patientDao.findByCode(patientDevice.getUser());
            if (patient != null) {
                object.put("userName", patient.getName());
            }
            objects.put(object);
        }
        return objects;
    }

    /**
     * 获取血糖仪各个时间段（无参为默认时间段）
     *
     * @param user
     * @param deviceSN
     * @return
     */
    public Map getBloodSuggerTime(String user, String deviceSN) {
        Map map = new HashMap();
        PatientBloodSugger bloodSugger = null;
        PatientHealthTime patientHealthTime = null;
        if (!StringUtils.isEmpty(user) && !StringUtils.isEmpty(deviceSN)) {
            patientHealthTime = patientHealthTimeDao.findByUserAndSN(user, deviceSN);
        }

        String fastingStart = null;
        String fastingEnd = null;
        String afterBreakFastStart = null;
        String afterBreakFastEnd = null;
        String beforeLunchStart = null;
        String beforeLunchEnd = null;
        String afterLunchStart = null;
        String afterLunchEnd = null;
        String beforeDinnerStart = null;
        String beforeDinnerEnd = null;
        String afterDinnerStart = null;
        String afterDinnerEnd = null;
        String beforeSleepStart = null;
        String beforeSleepEnd = null;
        if (patientHealthTime == null) {

            bloodSugger = patientBloodSuggerDao.findRecent();

            fastingStart = bloodSugger.getFastingStart();
            fastingEnd = bloodSugger.getFastingEnd();
            afterBreakFastStart = bloodSugger.getAfterBreakfastStart();
            afterBreakFastEnd = bloodSugger.getAfterBreakfastEnd();
            beforeLunchStart = bloodSugger.getBeforeLunchStart();
            beforeLunchEnd = bloodSugger.getBeforeLunchEnd();
            afterLunchStart = bloodSugger.getAfterLunchStart();
            afterLunchEnd = bloodSugger.getAfterLunchEnd();
            beforeDinnerStart = bloodSugger.getBeforeDinnerStart();
            beforeDinnerEnd = bloodSugger.getBeforeDinnerEnd();
            afterDinnerStart = bloodSugger.getAfterDinnerStart();
            afterDinnerEnd = bloodSugger.getAfterDinnerEnd();
            beforeSleepStart = bloodSugger.getBeforeSleepStart();
            beforeSleepEnd = bloodSugger.getBeforeSleepEnd();
        } else {
            fastingStart = patientHealthTime.getFastingStart();
            fastingEnd = patientHealthTime.getFastingEnd();
            afterBreakFastStart = patientHealthTime.getAfterBreakfastStart();
            afterBreakFastEnd = patientHealthTime.getAfterBreakfastEnd();
            beforeLunchStart = patientHealthTime.getBeforeLunchStart();
            beforeLunchEnd = patientHealthTime.getBeforeLunchEnd();
            afterLunchStart = patientHealthTime.getAfterLunchStart();
            afterLunchEnd = patientHealthTime.getAfterLunchEnd();
            beforeDinnerStart = patientHealthTime.getBeforeDinnerStart();
            beforeDinnerEnd = patientHealthTime.getBeforeDinnerEnd();
            afterDinnerStart = patientHealthTime.getAfterDinnerStart();
            afterDinnerEnd = patientHealthTime.getAfterDinnerEnd();
            beforeSleepStart = patientHealthTime.getBeforeSleepStart();
            beforeSleepEnd = patientHealthTime.getBeforeSleepEnd();
        }
        map.put("fasting", fastingStart + " - " + fastingEnd);
        map.put("afterBreakFast", afterBreakFastStart + " - " + afterBreakFastEnd);
        map.put("beforeLunch", beforeLunchStart + " - " + beforeLunchEnd);
        map.put("afterLunch", afterLunchStart + " - " + afterLunchEnd);
        map.put("beforeDinner", beforeDinnerStart + " - " + beforeDinnerEnd);
        map.put("afterDinner", afterDinnerStart + " - " + afterDinnerEnd);
        map.put("beforeSleep", beforeSleepStart + " - " + beforeSleepEnd);
        return map;
    }

    /**
     * 用户自定义血糖仪各个时间段
     *
     * @param fastingStart
     * @param fastingEnd
     * @param afterBreakfastStart
     * @param afterBreakfastEnd
     * @param beforeLunchStart
     * @param beforeLunchEnd
     * @param afterLunchStart
     * @param afterLunchEnd
     * @param beforeDinnerStart
     * @param beforeDinnerEnd
     * @param afterDinnerStart
     * @param afterDinnerEnd
     * @param beforeSleepStart
     * @param beforeSleepEnd
     */
    public void setBloodTime(String user, String deviceSN, String fastingStart, String fastingEnd, String afterBreakfastStart, String afterBreakfastEnd, String beforeLunchStart, String beforeLunchEnd,
                             String afterLunchStart, String afterLunchEnd, String beforeDinnerStart, String beforeDinnerEnd, String afterDinnerStart, String afterDinnerEnd,
                             String beforeSleepStart, String beforeSleepEnd) throws Exception {
        if (StringUtils.isEmpty(fastingStart) && StringUtils.isEmpty(fastingEnd) && StringUtils.isEmpty(afterBreakfastStart) && StringUtils.isEmpty(afterBreakfastEnd) && StringUtils.isEmpty(beforeLunchStart)
                && StringUtils.isEmpty(beforeLunchEnd) && StringUtils.isEmpty(afterLunchStart) && StringUtils.isEmpty(afterLunchEnd) && StringUtils.isEmpty(beforeDinnerStart) && StringUtils.isEmpty(beforeDinnerEnd) && StringUtils.isEmpty(afterDinnerStart)
                && StringUtils.isEmpty(afterDinnerEnd) && StringUtils.isEmpty(beforeSleepStart) && StringUtils.isEmpty(beforeSleepEnd)) {
            patientHealthTimeDao.deleteByUserAndSN(user, deviceSN);
            return;
        }
        PatientHealthTime healthTime = patientHealthTimeDao.findByUserAndSN(user, deviceSN);
        if (healthTime == null) {
            PatientHealthTime patientHealthTime = new PatientHealthTime();
            patientHealthTime.setUser(user);
            patientHealthTime.setDeviceSN(deviceSN);
            patientHealthTime.setFastingStart(fastingStart);
            patientHealthTime.setFastingEnd(fastingEnd);
            patientHealthTime.setAfterBreakfastStart(afterBreakfastStart);
            patientHealthTime.setAfterBreakfastEnd(afterBreakfastEnd);
            patientHealthTime.setBeforeLunchStart(beforeLunchStart);
            patientHealthTime.setBeforeLunchEnd(beforeLunchEnd);
            patientHealthTime.setAfterLunchStart(afterLunchStart);
            patientHealthTime.setAfterLunchEnd(afterLunchEnd);
            patientHealthTime.setBeforeDinnerStart(beforeDinnerStart);
            patientHealthTime.setBeforeDinnerEnd(beforeDinnerEnd);
            patientHealthTime.setAfterDinnerStart(afterDinnerStart);
            patientHealthTime.setAfterDinnerEnd(afterDinnerEnd);
            patientHealthTime.setBeforeSleepStart(beforeSleepStart);
            patientHealthTime.setBeforeSleepEnd(beforeSleepEnd);
            patientHealthTime.setDel(1);
            patientHealthTime.setCzrq(new Date());
            patientHealthTimeDao.save(patientHealthTime);
        } else {
            int rows = patientHealthTimeDao.modifyByUserAndSN(fastingStart, fastingEnd, afterBreakfastStart, afterBreakfastEnd, beforeLunchStart, beforeLunchEnd,
                    afterLunchStart, afterLunchEnd, beforeDinnerStart, beforeDinnerEnd, afterDinnerStart, afterDinnerEnd, beforeSleepStart, beforeSleepEnd, user, deviceSN);
            int str = rows;
        }

    }

    /**
     * 根据user，deviceSN修改血糖时间段
     * @param user
     * @param deviceSN
     * @param newDeviceSN
     * @throws Exception
     */
    public void updateDeviceSN(String user, String deviceSN, String newDeviceSN) throws Exception {
        patientHealthTimeDao.updateDeviceSN(user, deviceSN, newDeviceSN);
    }

    /**
     * 根据user，deviceSN更换绑定血糖仪
     * @param user
     * @param deviceSN
     * @param newDeviceSN
     * @throws Exception
     */
    public int updatePatientDevice(String user, String deviceSN, String newDeviceSN,String userType) throws Exception {
        int rows = patientDeviceDao.updatePatientDevice(user,deviceSN,newDeviceSN,userType);
        return rows;
    }


}
