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

import com.zhongshu.card.client.model.devices.userCache.UserCacheModel;
import com.zhongshu.card.client.type.DataState;
import com.zhongshu.card.client.type.UserState;
import com.zhongshu.card.server.core.dao.devices.DeviceGroupToDeviceDao;
import com.zhongshu.card.server.core.dao.devices.DeviceInfoDao;
import com.zhongshu.card.server.core.dao.devices.UserPermissDataCacheDao;
import com.zhongshu.card.server.core.dao.org.OrganizationUserDao;
import com.zhongshu.card.server.core.dao.org.UserCountDao;
import com.zhongshu.card.server.core.dao.org.UserGroupDao;
import com.zhongshu.card.server.core.dao.org.UserGroupToUserDao;
import com.zhongshu.card.server.core.dataConfig.TtlConfig;
import com.zhongshu.card.server.core.domain.devices.DeviceGroup;
import com.zhongshu.card.server.core.domain.devices.DeviceGroupToDevice;
import com.zhongshu.card.server.core.domain.devices.DeviceInfo;
import com.zhongshu.card.server.core.domain.devices.permiss.UserPermissDataCache;
import com.zhongshu.card.server.core.domain.org.OrganizationUser;
import com.zhongshu.card.server.core.domain.org.UserAccount;
import com.zhongshu.card.server.core.domain.org.UserGroup;
import com.zhongshu.card.server.core.domain.org.UserGroupToUser;
import com.zhongshu.card.server.core.event.DevicePermissChangeEvent;
import com.zhongshu.card.server.core.event.UserInfoChangeSyncEvent;
import com.zhongshu.card.server.core.service.base.SuperService;
import com.zhongshu.card.server.core.service.org.OrganizationUserServiceImpl;
import lombok.SneakyThrows;
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.event.EventListener;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 用户权限数据  缓存
 *
 * @author TRX
 * @date 2024/12/27
 */
@Slf4j
@Service
public class UserPermissDataCacheService extends SuperService {

    @Autowired
    private OrganizationUserDao organizationUserDao;

    @Autowired
    private OrganizationUserServiceImpl organizationUserService;

    @Autowired
    private UserGroupDao userGroupDao;

    @Autowired
    private UserGroupToUserDao userGroupToUserDao;

    @Autowired
    private UserCountDao userCountDao;

    @Autowired
    private UserPermissDataCacheDao userPermissDataCacheDao;

    @Autowired
    private DeviceInfoDao deviceInfoDao;

    @Autowired
    private DeviceGroupToDeviceDao deviceGroupToDeviceDao;

    @EventListener(classes = UserInfoChangeSyncEvent.class)
    @SneakyThrows
    public void userPermissDataChange(UserInfoChangeSyncEvent event) {
        log.info("userPermissDataChange: {}", event.getFrom());
        String projectOid = event.getProjectOid();
        List<String> userIds = event.getUserIds();
        if (ObjectUtils.isNotEmpty(userIds) && StringUtils.isNotEmpty(projectOid)) {
            for (String userId : userIds) {
                updateUserDevicePermissAboutInfo(userId, projectOid);
            }
        }
    }

    @EventListener(classes = DevicePermissChangeEvent.class)
    @SneakyThrows
    public void devicePermissDataChange(DevicePermissChangeEvent event) {
        log.info("devicePermissDataChange: {}", event.getFrom());
        String projectOid = event.getProjectOid();
        List<String> deviceIds = event.getDeviceIds();
        if (ObjectUtils.isNotEmpty(deviceIds) && StringUtils.isNotEmpty(projectOid)) {
            for (String deviceId : deviceIds) {
                updateDevicePermissAboutInfo(deviceId, projectOid);
            }
        }
    }

    /**
     * 缓存用户
     *
     * @param userId
     * @param projectOid
     */
    private UserPermissDataCache updateUserDevicePermissAboutInfo(String userId, String projectOid) {
        UserPermissDataCache dataCache = userPermissDataCacheDao.findTopByDataIdAndProjectOid(userId, projectOid);
        if (ObjectUtils.isEmpty(dataCache)) {
            dataCache = new UserPermissDataCache();
            dataCache.setTTL(new Date(System.currentTimeMillis() + TtlConfig.userCacheTime));
            dataCache.setDataId(userId);
            dataCache.setProjectOid(projectOid);
        }

        // 影响范围：用户项目中：机构、角色、分户分组、性别
        UserCacheModel model = new UserCacheModel();
        UserAccount userAccount = userCountDao.findTopByUserId(userId);
        if (ObjectUtils.isNotEmpty(userAccount)) {
            dataCache.setDataName(userAccount.getName());
            if (userAccount.getState() != UserState.Normal) {
                model.setFailed("用户不可用");
            } else {
                List<OrganizationUser> organizationUsers = organizationUserService.getUserOrgList(userId, projectOid);
                if (ObjectUtils.isNotEmpty(organizationUsers)) {
                    model.add(userId);
                    model.setSex(userAccount.getSex());

                    organizationUsers.parallelStream().forEach(organizationUser -> {
                        model.add(organizationUser.getOid());
                        if (ObjectUtils.isNotEmpty(organizationUser.getRoleIds())) {
                            model.addAll(organizationUser.getRoleIds());
                        }
                    });

                    // 用户分组
                    List<UserGroupToUser> userGroupToUsers = userGroupToUserDao.findByUserIdAndProjectOid(userId, projectOid);
                    if (ObjectUtils.isNotEmpty(organizationUsers)) {
                        userGroupToUsers.parallelStream().forEach(userGroupToUser -> {
                            UserGroup userGroup = userGroupToUser.getUserGroup();
                            if (ObjectUtils.isNotEmpty(userGroup) && userGroup.getState() == DataState.Enable) {
                                model.add(userGroup.getId());
                            }
                        });
                    }
                    model.setSuccess();
                } else {
                    model.setFailed("用户未加入项目");
                }
            }
        } else {
            model.setFailed("用户不存在");
        }
        dataCache.setCacheData(model);
        userPermissDataCacheDao.save(dataCache);
        return dataCache;
    }

    /**
     * 更新设备的权限数据
     *
     * @param deviceId
     * @param projectOid
     * @return
     */
    private UserPermissDataCache updateDevicePermissAboutInfo(String deviceId, String projectOid) {
        UserPermissDataCache dataCache = userPermissDataCacheDao.findTopByDataIdAndProjectOid(deviceId, projectOid);
        if (ObjectUtils.isEmpty(dataCache)) {
            dataCache = new UserPermissDataCache();
            dataCache.setTTL(new Date(System.currentTimeMillis() + TtlConfig.userCacheTime));
            dataCache.setDataId(deviceId);
            dataCache.setProjectOid(projectOid);
        }

        // 影响范围：用户项目中：机构、角色、分户分组、性别
        UserCacheModel model = new UserCacheModel();

        DeviceInfo deviceInfo = deviceInfoDao.findTopByDeviceId(deviceId);
        if (ObjectUtils.isNotEmpty(deviceInfo)) {
            dataCache.setDataName(deviceInfo.getDeviceName());

            if (deviceInfo.getState() != DataState.Enable) {
                model.setFailed("设备不可用");
            } else {
                model.add(deviceId);
                model.setDeviceType(deviceInfo.getDeviceType());
                if (StringUtils.isNotEmpty(deviceInfo.getAreaId())) {
                    // 区域的下级怎么办？
                    model.add(deviceInfo.getAreaId());
                }

                // 设备分组
                List<DeviceGroupToDevice> deviceAbouts = deviceGroupToDeviceDao.findByProjectOidAndDeviceId(projectOid, deviceId);
                if (ObjectUtils.isNotEmpty(deviceAbouts)) {
                    deviceAbouts.parallelStream().forEach(it -> {
                        DeviceGroup deviceGroup = it.getDeviceGroup();
                        if (ObjectUtils.isNotEmpty(deviceGroup) && deviceGroup.getState() == DataState.Enable) {
                            model.add(deviceGroup.getId());
                        }
                    });
                }
                model.setSuccess();
            }
        } else {
            model.setFailed("设备不存在");
        }
        dataCache.setCacheData(model);
        userPermissDataCacheDao.save(dataCache);
        return dataCache;
    }

    public UserCacheModel getUserCacheModel(String userId, String projectOid) {
        UserCacheModel model = null;
        UserPermissDataCache dataCache = userPermissDataCacheDao.findTopByDataIdAndProjectOid(userId, projectOid);
        if (ObjectUtils.isEmpty(dataCache)) {
            dataCache = updateUserDevicePermissAboutInfo(userId, projectOid);
        }
        if (ObjectUtils.isNotEmpty(dataCache)) {
            model = (UserCacheModel) dataCache.getCacheData();
        }
        return model;
    }

    public UserCacheModel getDeviceCacheModel(String deviceId, String projectOid) {
        UserCacheModel model = null;
        UserPermissDataCache dataCache = userPermissDataCacheDao.findTopByDataIdAndProjectOid(deviceId, projectOid);
        if (ObjectUtils.isEmpty(dataCache)) {
            dataCache = updateDevicePermissAboutInfo(deviceId, projectOid);
        }
        if (ObjectUtils.isNotEmpty(dataCache)) {
            model = (UserCacheModel) dataCache.getCacheData();
        }
        return model;
    }

    public Map<String, UserCacheModel> getUserAndDeviceCacheData(String userId, String deviceId, String projectOid) {
        Map<String, UserCacheModel> map = new HashMap<>();
        List<UserPermissDataCache> list = userPermissDataCacheDao.findByDataIdInAndProjectOid(List.of(userId, deviceId), projectOid);
        if (ObjectUtils.isNotEmpty(list) && list.size() == 2) {
            map = list.stream().collect(Collectors.toMap(
                    it -> it.getDataId(), it -> {
                        return (UserCacheModel) it.getCacheData();
                    }));
        } else {
            UserCacheModel model = getUserCacheModel(userId, projectOid);
            map.put(userId, model);

            UserCacheModel model1 = getDeviceCacheModel(deviceId, projectOid);
            map.put(deviceId, model1);
        }
        return map;
    }

}
