package com.fs.watch.service.impl;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.fs.common.exception.CustomException;
import com.fs.common.exception.ServiceException;
import com.fs.common.utils.DateUtils;
import com.fs.common.utils.StringUtils;
import com.fs.company.domain.CompanyUserUser;
import com.fs.company.service.ICompanyService;
import com.fs.company.service.ICompanyUserService;
import com.fs.company.service.ICompanyUserUserService;
import com.fs.his.domain.FsInquiryOrder;
import com.fs.his.domain.FsUser;
import com.fs.his.service.IFsDoctorService;
import com.fs.his.service.IFsInquiryOrderService;
import com.fs.his.service.IFsUserService;
import com.fs.his.vo.FsUserAndCompanyAndDoctorVo;
import com.fs.watch.domain.DeviceFamily;
import com.fs.watch.domain.WatchBasicInfo;
import com.fs.watch.domain.WatchDeviceInfo;
import com.fs.watch.domain.vo.WatchDeviceInfoVo;
import com.fs.watch.domain.vo.WatchLastHealthDataVo;
import com.fs.watch.mapper.WatchDeviceInfoMapper;
import com.fs.watch.param.WatchDeviceInfoQueryParam;
import com.fs.watch.service.*;
import com.fs.watch.utils.MyHttpUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

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

/**
 * @author Administrator
 * @description 针对表【watch_device_info(设备硬件信息)】的数据库操作Service实现
 * @createDate 2024-10-15 11:06:50
 */
@Service
public class WatchDeviceInfoServiceImpl implements WatchDeviceInfoService {
    @Autowired
    private WatchDeviceInfoMapper mapper;

    @Autowired
    private WatchDataService watchDataService;


    @Autowired
    private WatchBasicInfoService watchBasicInfoService;


    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    @Autowired
    private DeviceSetUpService deviceSetUpService;

    @Autowired
    private ICompanyService companyService;
    @Autowired
    private ICompanyUserService companyUserService;
    @Autowired
    private IFsUserService userService;
    @Autowired
    private IFsDoctorService doctorService;

    @Autowired
    private ICompanyUserUserService companyUserUserService;

    @Autowired
    private IFsInquiryOrderService inquiryOrderService;




    /**
     * 新增设备信息
     *
     * @param deviceInfo 设备信息
     * @return 结果
     */
    @Override
    public int insertDeviceInfo(WatchDeviceInfo deviceInfo) {
        //查看该设备是否存在
        WatchDeviceInfoVo vo = getByNumber(deviceInfo.getDeviceNumber());
        if (vo != null) {
            throw new ServiceException("该设备已存在");
        }
        //检测设备是否存在
        Integer status = this.getStatus(deviceInfo.getDeviceNumber());
        if (status == 4 || status < 0) {
            throw new ServiceException().setMessage("设备不在线");
        }
        deviceInfo.setCreateTime(DateUtils.getNowDate());
        int i = mapper.insertDeviceInfo(deviceInfo);
        return i;
    }

    @Override
    public int updateByDeviceNumber(WatchDeviceInfo data) {
        if (data.getDeviceNumber() == null) {
            return 0;
        }
        WatchDeviceInfoVo vo = getByNumber(data.getDeviceNumber());
        if (vo == null) {
            //新增
            setCompanyAndDoctor(data); //更新相关公司及医生信息
            data.setCreateTime(DateUtils.getNowDate());

            return mapper.insertDeviceInfo(data);
        } else {
            //更新
            if (data.getFamilyUserId() == null){
                data.setFamilyUserId(vo.getFamilyUserId());
            }
            if (data.getUserId() == null){
                data.setUserId(vo.getUserId());
            }
            setCompanyAndDoctor(data); //更新相关公司及医生信息
            data.setUpdateTime(DateUtils.getNowDate());
            return mapper.updateByDeviceNumber(data);
        }
    }

    /**
     *
     * 更新相关公司及医生信息
     * @param data
     */
    private void setCompanyAndDoctor(WatchDeviceInfo data) {
        String userId = data.getUserId();
        String familyUserId = data.getFamilyUserId();
        StringBuffer companyIds = new StringBuffer();
        StringBuffer companyUserIds = new StringBuffer();
        StringBuffer doctorIds = new StringBuffer();
        if (StringUtils.isNotBlank(userId)) {
            selectCompanyAndDoctor(userId, companyIds, companyUserIds, doctorIds); //查询用户关联的公司及医生
            data.setUserId(userId);
        }
        if (StringUtils.isNotBlank(familyUserId)) {
            selectCompanyAndDoctor(familyUserId, companyIds, companyUserIds, doctorIds); //查询家人关联的公司及医生
            data.setFamilyUserId(familyUserId);
        }
        if (companyIds.length() > 0) {
            companyIds.deleteCharAt(companyIds.length() - 1);
        }
        if (companyUserIds.length() > 0) {
            companyUserIds.deleteCharAt(companyUserIds.length() - 1);
        }
        if (doctorIds.length() > 0) {
            doctorIds.deleteCharAt(doctorIds.length() - 1);
        }
        //更新去重公司医生信息
        data.setCompanyId(distinctId(String.valueOf(companyIds)));
        data.setCompanyUserId(distinctId(String.valueOf(companyUserIds)));
        data.setDoctorId(distinctId(String.valueOf(companyUserIds)));
        //设备状态
        if (StringUtils.isBlank(data.getUserId()) && StringUtils.isBlank(data.getDoctorId())) {
            data.setLifeStatus(0);
        } else {
            data.setLifeStatus(2);
        }
    }

    /**
     * 查询用户关联的公司及医生信息
     * @param userId
     * @param companyIds
     * @param companyUserIds
     * @param doctorIds
     */
    private void selectCompanyAndDoctor(String userId, StringBuffer companyIds, StringBuffer companyUserIds, StringBuffer doctorIds) {
        if (StringUtils.isNotBlank(userId)){
            //查询userId关联的公司及医生
            Arrays.asList(userId.split(",")).forEach(user -> {
                FsUserAndCompanyAndDoctorVo userVo = userService.selectCompanyAndDoctor(userId);
                if (userVo != null) {
                    if (StringUtils.isNotBlank(userVo.getCompanyId()) && !"null".equals(userVo.getCompanyUserId())) {
                        companyIds.append(userVo.getCompanyId()).append(",");

                    }
                    if (StringUtils.isNotBlank(userVo.getCompanyUserId()) && !"null".equals(userVo.getCompanyUserId())) {
                        companyUserIds.append(userVo.getCompanyUserId()).append(",");
                    }
                    if (StringUtils.isNotBlank(userVo.getDoctorId()) && !"null".equals(userVo.getDoctorId())) {
                        doctorIds.append(userVo.getDoctorId()).append(",");
                    }
                }
            });
        }
    }


    /**
     * 逗号拼接字符串去重
     * @param ids
     * @return newIds
     */
    private String distinctId(String ids) {
        if (StringUtils.isNotBlank(ids)){
            StringBuffer newIds = new StringBuffer();
            Arrays.stream(ids.split(",")).distinct().forEach(id->newIds.append(id).append(","));
            newIds.deleteCharAt(newIds.length() - 1);
            return newIds.toString();

        }
        return "";
    }

    @Override
    public int remove(String deviceNums) {
        return mapper.remove(deviceNums);
    }

    @Override
    public Map<String, Object> getInfo(String deviceNumber) {
        Map<String, Object> params = new HashMap<>();
        params.put("device_id", deviceNumber);
        //电量 信号
        WatchBasicInfo info = watchBasicInfoService.queryLastByDeviceId(deviceNumber);
        if (info != null) {
            System.out.println(info);
            Map<String, Object> map = new HashMap<>();
            map.put("rssi", info.getRssi());
            map.put("device_id", deviceNumber);
            map.put("battery", info.getBattery());
            //查询设备状态
            map.put("status",getStatus(deviceNumber));
            return map;
        }
        return null;
    }

    private Map<String, Object> getDeviceMap(WatchDeviceInfo deviceInfo) {
        Map<String, Object> params = new HashMap<>();
        params.put("device_id", deviceInfo.getDeviceId());
        params.put("companyId", deviceInfo.getCompanyId());
        params.put("deviceNumber", deviceInfo.getDeviceNumber());
        params.put("battery", deviceInfo.getBattery());
        params.put("rssi", deviceInfo.getRssi());
        params.put("status", deviceInfo.getStatus());
        params.put("createTime", DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, deviceInfo.getCreateTime()));
        params.put("createBy", deviceInfo.getCreateBy());
        params.put("updateTime", null);
        params.put("updateBy", deviceInfo.getUpdateBy());
        params.put("IsDel", deviceInfo.getIsDel());
        return params;
    }

    /**
     * 查询设备信息列表
     *
     * @param param 设备信息
     * @return 设备信息
     */
    @Override
    public List<WatchDeviceInfoVo> selectDeviceInfoList(WatchDeviceInfoQueryParam param) {
        List<WatchDeviceInfoVo> watchDeviceInfoVos = mapper.selectDeviceInfoList(param);

        if (param.getLifeStatus() != null && param.getLifeStatus() == 0) {
            return watchDeviceInfoVos;
        }

        List<CompletableFuture<Void>> futures = new ArrayList<>();
        for (WatchDeviceInfoVo watchDeviceInfoVo : watchDeviceInfoVos) {
            CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                // 异步查询公司信息
                CompletableFuture<Void> companyFuture = CompletableFuture.runAsync(() -> {
                    queryCompanyInfo(watchDeviceInfoVo);
                }, threadPoolTaskExecutor);

                // 异步查询公司用户信息
                CompletableFuture<Void> companyUserFuture = CompletableFuture.runAsync(() -> {
                    queryCompanyUserInfo(watchDeviceInfoVo);
                }, threadPoolTaskExecutor);

                // 异步查询医生信息
                CompletableFuture<Void> doctorFuture = CompletableFuture.runAsync(() -> {
                    queryDoctorInfo(watchDeviceInfoVo);
                }, threadPoolTaskExecutor);

                // 异步查询用户信息
                CompletableFuture<Void> userFuture = CompletableFuture.runAsync(() -> {
                    queryUserInfo(watchDeviceInfoVo);
                }, threadPoolTaskExecutor);

                // 异步查询家人用户信息
                CompletableFuture<Void> familyUserFuture = CompletableFuture.runAsync(() -> {
                    queryFamilyUserInfo(watchDeviceInfoVo);
                }, threadPoolTaskExecutor);

                // 异步查询设备状态
                CompletableFuture<Void> deviceStatusFuture = CompletableFuture.runAsync(() -> {
                    queryDeviceStatus(watchDeviceInfoVo);
                }, threadPoolTaskExecutor);

                // 异步查询健康数据并判断健康状态
                CompletableFuture<Void> healthDataFuture = CompletableFuture.runAsync(() -> {
                    queryHealthDataAndJudgeStatus(watchDeviceInfoVo);
                }, threadPoolTaskExecutor);

                // 等待所有异步任务完成
                CompletableFuture.allOf(
                        companyFuture,
                        companyUserFuture,
                        doctorFuture,
                        userFuture,
                        familyUserFuture,
                        deviceStatusFuture,
                        healthDataFuture
                ).join();

            }, threadPoolTaskExecutor);
            futures.add(future);
        }

        // 等待所有设备信息处理任务完成
        CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
        return watchDeviceInfoVos;
    }

    /**
     * 查询公司信息
     * @param watchDeviceInfoVo
     */
    private void queryCompanyInfo(WatchDeviceInfoVo watchDeviceInfoVo) {
        String companyId = watchDeviceInfoVo.getCompanyId();
        if (StringUtils.isNotBlank(companyId)) {
            watchDeviceInfoVo.setCompanyName(companyService.selectCompanyByIds(companyId));
        }
    }

    /**
     * 查询公司用户信息
     * @param watchDeviceInfoVo
     */
    private void queryCompanyUserInfo(WatchDeviceInfoVo watchDeviceInfoVo) {
        String companyUserId = watchDeviceInfoVo.getCompanyUserId();
        if (StringUtils.isNotBlank(companyUserId)) {
            watchDeviceInfoVo.setCompanyUserName(companyUserService.selectCompanyUserByIds(companyUserId));
        }
    }

    /**
     * 查询医生信息
     * @param watchDeviceInfoVo
     */
    private void queryDoctorInfo(WatchDeviceInfoVo watchDeviceInfoVo) {
        String doctorId = watchDeviceInfoVo.getDoctorId();
        if (StringUtils.isNotBlank(doctorId)) {
            watchDeviceInfoVo.setDoctorName(doctorService.selectDoctorByIds(doctorId));
        }
    }

    /**
     * 查询用户信息
     * @param watchDeviceInfoVo
     */
    private void queryUserInfo(WatchDeviceInfoVo watchDeviceInfoVo) {
        String userId = watchDeviceInfoVo.getUserId();
        if (StringUtils.isNotBlank(userId)) {
            watchDeviceInfoVo.setUsers(userService.selectUserByIds(userId));
        }
    }

    /**
     * 查询家人用户信息
     * @param watchDeviceInfoVo
     */
    private void queryFamilyUserInfo(WatchDeviceInfoVo watchDeviceInfoVo) {
        String familyUserId = watchDeviceInfoVo.getFamilyUserId();
        if (StringUtils.isNotBlank(familyUserId)) {
            watchDeviceInfoVo.setFamilyUsers(userService.selectUserByIds(familyUserId));
        }
    }

    /**
     * 查询设备状态
     * @param watchDeviceInfoVo
     */
    private void queryDeviceStatus(WatchDeviceInfoVo watchDeviceInfoVo) {
        Integer deviceStatus = getStatus(watchDeviceInfoVo.getDeviceNumber());
        if (deviceStatus != null) {
            watchDeviceInfoVo.setStatus(deviceStatus);
        }
    }

    /**
     * 查询健康数据并判断健康状态
     * @param watchDeviceInfoVo
     */
    private void queryHealthDataAndJudgeStatus(WatchDeviceInfoVo watchDeviceInfoVo) {
        watchDeviceInfoVo.setIsNormal(watchDataService.queryHealthStatus(watchDeviceInfoVo.getDeviceNumber()) ? "正常" : "异常");
    }

    /**
     * 查询设备信息列表
     *
     * @return 设备信息
     */
    @Override
    public List<WatchDeviceInfo> selectByUserExist() {
        return mapper.selectByUserExist();
    }

    /**
     * 查询设备信息
     *
     * @param deviceId 设备信息主键
     * @return 设备信息
     */
    @Override
    public WatchDeviceInfoVo selectDeviceInfoByDeviceId(Long deviceId) {
        WatchDeviceInfoVo deviceInfoVo = mapper.selectDeviceInfoByDeviceId(deviceId);
        //同步设备信息
//        Map<String, Object> info = getInfo(deviceInfoVo.getDeviceNumber());
//        deviceInfoVo.setRssi(Integer.valueOf(info.get("rssi").toString()));
//        deviceInfoVo.setBattery(Integer.valueOf(info.get("battery").toString()));
//        deviceInfoVo.setStatus(Integer.valueOf(info.get("status").toString()));
//        updateDeviceInfo(deviceInfoVo);
        return deviceInfoVo;
    }

    /**
     * 修改设备信息
     *
     * @param deviceInfo 设备信息
     * @return 结果
     */
    @Override
    public int updateDeviceInfo(WatchDeviceInfo deviceInfo) {
        //检测设备是否存在
//        Integer status = this.getStatus(deviceInfo.getDeviceNumber());
//        if (status == 4 || status < 0) {
//            throw new CustomException("设备不在线");
//        }
        Date nowDate = DateUtils.getNowDate();
        deviceInfo.setUpdateTime(nowDate);
        return mapper.updateDeviceInfo(deviceInfo);
    }

    @Override
    public WatchDeviceInfoVo getByNumber(String number) {
        return mapper.getByNumber(number);
    }

    @Override
    public Integer getStatus(String deviceId) {
        //访问接口直接查询状态
        return deviceSetUpService.status(deviceId);
    }


    /**
     * 批量删除设备信息
     *
     * @param deviceIds 需要删除的设备信息主键
     * @return 结果
     */
    @Override
    public int deleteDeviceInfoByDeviceIds(Long[] deviceIds) {
        int result = mapper.deleteDeviceInfoByDeviceIds(deviceIds);
        return result;
    }

    /**
     * 改变家人绑定信息 更新设备表
     * @param oldOtherDevice
     * @param newOtherDevice
     * @param userId
     */
    @Override
    public void updateDeviceInfoByOtherDevice(String oldOtherDevice, String newOtherDevice,String userId) {
        //1.转列表
        List<DeviceFamily> newList = getValidFamilies(newOtherDevice);
        List<DeviceFamily> oldList = getValidFamilies(oldOtherDevice);
        //2.修改watch_device_info 表
        if (!oldList.isEmpty()){
            if (!newList.isEmpty()){
                //新增部分
//                final List<DeviceFamily> finalOldList = oldList;
                newList.forEach(deviceFamily -> {
                    String deviceIds = deviceFamily.getDeviceId();
                    Arrays.stream(deviceIds.split(",")).forEach(deviceId -> {
                        if (!oldOtherDevice.contains(deviceId)){
                            //不包含则新增
                            addFamilyUser(userId, deviceId);
                        }
                    });

                });

                //移除部分
                oldList.forEach(deviceFamily -> {
                    String deviceIds = deviceFamily.getDeviceId();
                    Arrays.stream(deviceIds.split(",")).forEach(deviceId -> {
                        if (!newOtherDevice.contains(deviceId)){
                            //不包含则移除
                            subFamilyUser(userId, deviceId);
                        }
                    });
                });

            } else {
                //全移除
                subFamilyUser(userId, oldList);
            }
        } else {
            if (!newList.isEmpty()){
                //全新增
                newList.forEach(deviceFamily -> {
                    addFamilyUser(userId, deviceFamily.getDeviceId());
                });
            }
        }
    }

    @Override
    public void updateDeviceInfoByDevice(String deviceId, String userId) {
        WatchDeviceInfo watchDeviceInfo = new WatchDeviceInfo();
        watchDeviceInfo.setDeviceNumber(deviceId);
        WatchDeviceInfoVo vo = getByNumber(deviceId);
        if (vo != null){
            String userIds = vo.getUserId();
            userIds = getDistinctUserId(userId, userIds);
            watchDeviceInfo.setUserId(userIds);

        }else {
            watchDeviceInfo.setUserId(userId);
        }
        updateByDeviceNumber(watchDeviceInfo);
    }

    /**
     * 查询有设备编号的家人信息
     * @param str
     * @return list
     */
    private List<DeviceFamily> getValidFamilies(String str) {
        List<DeviceFamily> list = new ArrayList<>();
        if (StringUtils.isNotBlank(str)){
            //去除没有Device的家人信息
            JSONUtil.parseArray(str).toList(DeviceFamily.class).forEach(item->{
                if (StringUtils.isNotBlank(item.getDeviceId())){
                    list.add(item);
                }
            });
        }
        return list;
    }

    private void addFamilyUser(String userId, String deviceIds) {
            Arrays.stream(deviceIds.split(",")).forEach(deviceId->{
                WatchDeviceInfo watchDeviceInfo = new WatchDeviceInfo();
                watchDeviceInfo.setDeviceNumber(deviceId);
                WatchDeviceInfoVo vo = getByNumber(deviceId);
                if (vo != null){
                    String userIds = vo.getFamilyUserId();
                    userIds = getDistinctUserId(userId, userIds);
                    watchDeviceInfo.setFamilyUserId(userIds);

                } else {
                    watchDeviceInfo.setFamilyUserId(userId);
                }
                updateByDeviceNumber(watchDeviceInfo);
            });

    }

    private String getDistinctUserId(String userId, String userIds) {
        if (StringUtils.isNotBlank(userIds)) {
                userIds = userIds + "," + userId;
                //去重
                StringBuffer newUserIds = new StringBuffer();
                Arrays.stream(userIds.split(",")).distinct().forEach(item-> newUserIds.append(item).append(","));
                newUserIds.deleteCharAt(newUserIds.length()-1);
                userIds = newUserIds.toString();
        }else {
            userIds = userId;
        }
        return userIds;
    }

    private void subFamilyUser(String userId, String deviceId) {
            WatchDeviceInfoVo vo = getByNumber(deviceId);
            if (vo != null){
                //更新
                String familyUserId = vo.getFamilyUserId();
                if (StringUtils.isNotBlank(familyUserId)){
                    WatchDeviceInfo info = new WatchDeviceInfo();
                    info.setFamilyUserId(subId(familyUserId, userId));
                    info.setDeviceNumber(deviceId);
                    updateByDeviceNumber(info);
                }
            }
    }

    private void subFamilyUser(String userId, List<DeviceFamily> list) {
        list.forEach(deviceFamily -> {
            String deviceIds = deviceFamily.getDeviceId();
            Arrays.stream(deviceIds.split(",")).forEach(deviceId->{
                WatchDeviceInfoVo vo = getByNumber(deviceId);
                if (vo != null){
                    //更新
                    String familyUserId = vo.getFamilyUserId();
                    if (StringUtils.isNotBlank(familyUserId)){
                        WatchDeviceInfo info = new WatchDeviceInfo();
                        info.setFamilyUserId(subId(familyUserId, userId));
                        info.setDeviceNumber(deviceId);
                        updateByDeviceNumber(info);
                    }
                }
            });
        });
    }

    private String subId(String ids, String id) {
        StringBuilder finalIds = new StringBuilder();
         Arrays.stream(ids.split(",")).forEach(oldId->{
             if (!id.equals(oldId)){
                 finalIds.append(oldId).append(",");
             }
         });

        if (finalIds.length() > 0){
             finalIds.deleteCharAt(finalIds.length() - 1);
         }
        return finalIds.toString();
    }

}
