package com.zhongshu.card.server.core.service.devices.permiss;

import com.github.microservice.core.util.os.SystemUtil;
import com.github.microservice.models.device.DevicePerQuery;
import com.github.microservice.models.devicePermiss.DeviceAboutPermiss;
import com.github.microservice.models.devicePermiss.DeviceUsersInfo;
import com.github.microservice.models.devicePermiss.GateWayPermissModel;
import com.github.microservice.models.devicePermiss.ProjectUserPermiss;
import com.github.microservice.net.ResultContent;
import com.google.common.collect.Lists;
import com.zhongshu.card.client.type.DataState;
import com.zhongshu.card.server.core.dao.devices.DevicePermissDao;
import com.zhongshu.card.server.core.dataConfig.CardSystemDefault;
import com.zhongshu.card.server.core.domain.devices.permiss.DevicePermiss;
import com.zhongshu.card.server.core.domain.org.UserAccount;
import com.zhongshu.card.server.core.domain.projectAbout.OrgUserFace;
import com.zhongshu.card.server.core.domain.school.CardInfo;
import com.zhongshu.card.server.core.service.projectAbout.CardInfoServiceImpl;
import com.zhongshu.card.server.core.service.projectAbout.OrgUserFaceService;
import com.zhongshu.card.server.core.service.user.UserAccountServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

/**
 * 设备权限 （绑定用户）管理
 *
 * @author TRX
 * @date 2024/10/11
 */
@Slf4j
@Service
public class DevicePermissIotService {

    @Autowired
    private OrgUserFaceService orgUserFaceService;

    @Autowired
    private CardInfoServiceImpl cardInfoService;

    @Autowired
    private DevicePermissDao devicePermissDao;

    @Autowired
    private DevicePermissEventService devicePermissEventService;

    @Autowired
    private UserAccountServiceImpl userAccountService;

    //线程池
    private ExecutorService executorService = Executors.newFixedThreadPool(SystemUtil.getCpuCoreCount() * 2);

    @Autowired
    private UserCanUseDeviceService userCanUseDeviceService;

    @Autowired
    private void init(ApplicationContext applicationContext) {
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            executorService.shutdownNow();
        }));
    }

    /**
     * 组装设备权限变更的数据
     *
     * @param permisses DevicePermiss 设备用户绑定数据ID
     * @param mark      0: 删除   1：新增、修改   2：全量
     * @return
     */
    public ResultContent changeDeviceUser(List<DevicePermiss> permisses, int mark, String groupId) {
        if (ObjectUtils.isNotEmpty(permisses)) {
            executorService.execute(() -> {
                Map<String, List<DevicePermiss>> map = permisses.stream().collect(Collectors.groupingBy(DevicePermiss::getGateWayId));

                map.forEach((gateWayId, tempList) -> {
                    GateWayPermissModel gateWayPermissModel = new GateWayPermissModel();
                    gateWayPermissModel.setGateWayId(gateWayId);
                    gateWayPermissModel.setGroupId(groupId);

                    List<DeviceAboutPermiss> devices = tempList.stream().map(it -> {
                        DeviceAboutPermiss permiss = new DeviceAboutPermiss();
                        permiss.setDeviceId(it.getDeviceId());
                        permiss.addUser(it.getUserId());
                        //TODO
                        List<String> ids = new ArrayList<>();
                        for (int i = 0; i < 10000; i++) {
//                            ids.add(CommonUtil.UUID());
                        }
                        permiss.addUsers(ids);
                        permiss.setMark(mark);
                        return permiss;
                    }).collect(Collectors.toUnmodifiableList());
                    gateWayPermissModel.setDevices(devices);

                    // 下发设备数据
                    devicePermissEventService.requestDeviceBindData(gateWayPermissModel, tempList.get(0).getProjectOid());
                });
            });
        }
        return ResultContent.buildSuccess();
    }

    /**
     * 下发用户信息数据
     *
     * @param permisses
     * @param mark
     * @return
     */
    public ResultContent changeUserInfo(List<DevicePermiss> permisses, int mark) {
        if (ObjectUtils.isNotEmpty(permisses)) {
            Map<String, List<DevicePermiss>> map = permisses.stream().collect(Collectors.groupingBy(DevicePermiss::getGateWayId));
            map.forEach((gateWayId, tempList) -> {
                DeviceUsersInfo deviceUsersInfo = new DeviceUsersInfo();
                deviceUsersInfo.setGateWayId(gateWayId);
                String projectOid = tempList.get(0).getProjectOid();
                // 用户数据 (去重)
                List<String> userIds = tempList.stream().map(it -> it.getUserId()).distinct().collect(Collectors.toList());
                List<ProjectUserPermiss> userPermiss = getUserPermiss(projectOid, userIds);

                deviceUsersInfo.setUsers(userPermiss);
                // 下发用户数据
                devicePermissEventService.requestDevicesUsersData(deviceUsersInfo, projectOid);
            });
        }
        return ResultContent.buildSuccess();
    }

    /**
     * 组装设备 关联的用户下发数据 {deviceId: [userIds]}
     * @param query
     * @return
     */
    public GateWayPermissModel queryDevicePermissInfo(DevicePerQuery query) {
        GateWayPermissModel permissModel = getDeviceAboutUsers(query.getDeviceIds());
        permissModel.setSuccess();
        permissModel.setGateWayId(query.getGatewayId());
        return permissModel;
    }

    /**
     * @param query
     * @return
     */
    public DeviceUsersInfo queryDeviceAboutUsers(DevicePerQuery query) {
        DeviceUsersInfo permissModel = getDeviceAboutUserInfos(query.getDeviceIds());
        permissModel.setSuccess();
        permissModel.setGateWayId(query.getGatewayId());
        return permissModel;
    }

    public DeviceUsersInfo getDeviceAboutUserInfos(List<String> deviceIds) {
        DeviceUsersInfo deviceUsersInfo = new DeviceUsersInfo();
        if (ObjectUtils.isNotEmpty(deviceIds)) {
            List<DevicePermiss> list = devicePermissDao.findByDeviceIdInAndDataState(deviceIds, DataState.Enable);
            if (ObjectUtils.isNotEmpty(list)) {
                // 用户userId集合
                List<String> _userIds = list.stream().map(it -> it.getUserId()).collect(Collectors.toUnmodifiableList());
                List<ProjectUserPermiss> userPermiss = getUserPermiss(list.get(0).getProjectOid(), _userIds.stream().distinct().collect(Collectors.toList()));
                deviceUsersInfo.setUsers(userPermiss);
            }
        }
        return deviceUsersInfo;
    }

    /**
     * 组装用户在项目下的数据 mark：默认是1 ，编辑、增加 (用户名称、头像、卡片)
     *
     * @param projectOid 项目oid
     * @param userIds    用户userId集合
     * @return
     */
    public List<ProjectUserPermiss> getUserPermiss(String projectOid, List<String> userIds) {
        if (StringUtils.isNotEmpty(projectOid) && ObjectUtils.isNotEmpty(userIds)) {
            // 用户信息
            List<UserAccount> userAccounts = userAccountService.getUserAccounts(userIds);
            Map<String, UserAccount> userMap = userAccounts.stream().collect(Collectors.toMap(it -> it.getUserId(), it -> it, (v1, v2) -> v1));

            // 人脸信息
            List<OrgUserFace> userFaces = orgUserFaceService.getUserFaces(projectOid, userIds);
            Map<String, List<OrgUserFace>> faceMap = userFaces.stream().collect(Collectors.groupingBy(OrgUserFace::getUserId));

            // 用户的卡片信息
            List<CardInfo> cardInfos = cardInfoService.getProjectCards(projectOid, userIds);
            Map<String, List<CardInfo>> cardMap = cardInfos.stream().collect(Collectors.groupingBy(CardInfo::getUserId));

            Map<String, ProjectUserPermiss> map = new HashMap<>();
            for (String userId : userIds) {
                ProjectUserPermiss permiss = null;
                if (map.containsKey(userId)) {
                    permiss = map.get(userId);
                } else {
                    permiss = new ProjectUserPermiss();
                }
                permiss.setMark(2);
                permiss.setUid(userId);
                UserAccount userAccount = userMap.get(userId);
                if (ObjectUtils.isNotEmpty(userAccount)) {
                    permiss.setUn(userAccount.getName());
                }
                List<OrgUserFace> orgUserFaces = faceMap.get(userId);
                if (ObjectUtils.isNotEmpty(orgUserFaces)) {
                    permiss.setFi(orgUserFaces.get(0).getImg());
                } else {
                    // 给个默认的人脸
                    permiss.setFi(CardSystemDefault.defaultPermissFaceUrl);
                }
                List<CardInfo> cardInfoList = cardMap.get(userId);
                if (ObjectUtils.isNotEmpty(cardInfoList)) {
                    permiss.setCNos(cardInfoList.stream().map(it -> it.getCode()).collect(Collectors.toList()));
                } else {
//                    permiss.setCNos(List.of("unKnow"));
                }
                map.put(userId, permiss);
            }
            return List.copyOf(map.values());
        }
        return Lists.newArrayList();
    }

    /**
     * 得到设备关联的用户 （用户数据发生了变化，为什么要在权限表来查询数据诶？
     * 因为要来查询用户关联的设备->设备关联的网关，才能知道往那个网关推送数据
     *
     * @param deviceIds
     * @return
     */
    public GateWayPermissModel getDeviceAboutUsers(List<String> deviceIds) {
        GateWayPermissModel gateWayPermissModel = new GateWayPermissModel();
        if (ObjectUtils.isNotEmpty(deviceIds)) {
            for (String deviceId : deviceIds) {
                DeviceAboutPermiss aboutPermiss = new DeviceAboutPermiss();
                aboutPermiss.setMark(2);
                aboutPermiss.setDeviceId(deviceId);
                List<String> _userIds = userCanUseDeviceService.getDeviceUserIds(deviceId);
                aboutPermiss.setUserIds(_userIds);
                gateWayPermissModel.addDevice(aboutPermiss);
            }
        }
        return gateWayPermissModel;
    }

}
