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

import com.github.microservice.components.data.base.util.PageEntityUtil;
import com.github.microservice.core.util.os.SystemUtil;
import com.github.microservice.net.ResultContent;
import com.github.microservice.net.ResultMessage;
import com.google.common.collect.Lists;
import com.zhongshu.card.client.model.base.IDsParam;
import com.zhongshu.card.client.model.devices.permiss.DevicePermissModel;
import com.zhongshu.card.client.model.devices.permiss.DevicePermissParam;
import com.zhongshu.card.client.model.devices.permiss.DevicePermissSearch;
import com.zhongshu.card.client.model.org.OrganizationUserModel;
import com.zhongshu.card.client.type.DataOperationType;
import com.zhongshu.card.client.type.DataState;
import com.zhongshu.card.server.core.dao.devices.DeviceInfoDao;
import com.zhongshu.card.server.core.dao.devices.DevicePermissDao;
import com.zhongshu.card.server.core.dao.org.OrganizationDao;
import com.zhongshu.card.server.core.dao.org.OrganizationUserDao;
import com.zhongshu.card.server.core.domain.devices.DeviceInfo;
import com.zhongshu.card.server.core.domain.devices.permiss.DevicePermiss;
import com.zhongshu.card.server.core.domain.org.Organization;
import com.zhongshu.card.server.core.domain.org.OrganizationUser;
import com.zhongshu.card.server.core.domain.org.UserAccount;
import com.zhongshu.card.server.core.event.OrgUserBindUpdateSyncEvent;
import com.zhongshu.card.server.core.service.base.SuperService;
import com.zhongshu.card.server.core.service.devices.DeviceInfoServiceImpl;
import com.zhongshu.card.server.core.service.user.UserAccountServiceImpl;
import com.zhongshu.card.server.core.util.BeanUtils;
import com.zhongshu.card.server.core.util.CommonUtil;
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.ApplicationContext;
import org.springframework.context.event.EventListener;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
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 DevicePermissService extends SuperService {

    @Autowired
    private DevicePermissDao devicePermissDao;

    @Autowired
    private DeviceInfoServiceImpl deviceInfoService;

    @Autowired
    private UserAccountServiceImpl userAccountService;

    @Autowired
    private DeviceInfoDao deviceInfoDao;

    @Autowired
    private OrganizationDao organizationDao;

    @Autowired
    private OrganizationUserDao organizationUserDao;

    @Autowired
    private DevicePermissEventService devicePermissEventService;

    @Autowired
    private DevicePermissIotService devicePermissIotService;

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

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

    /**
     * 设备绑定用户
     *
     * @param param
     * @return
     */
    public ResultContent saveBindInfo(DevicePermissParam param) {
        String projectOid = param.getProjectOid();
        if (ObjectUtils.isEmpty(projectOid)) {
            return ResultContent.buildFail(String.format("projectOid不能为空"));
        }
        if (ObjectUtils.isEmpty(param.getDeviceIds())) {
            return ResultContent.buildFail("deviceIds不能为空");
        }
        List<String> ids = param.getIds();
        if (ObjectUtils.isEmpty(ids)) {
            return ResultContent.buildFail("ids is null");
        }
        // 设备数据
        List<DeviceInfo> deviceInfos = deviceInfoDao.findByDeviceIdIn(param.getDeviceIds());
        if (ObjectUtils.isEmpty(deviceInfos)) {
            return ResultContent.buildFail("未找到设备信息");
        }

        if (ObjectUtils.isNotEmpty(deviceInfos)) {
            // 机构用户数据
            List<OrganizationUser> orgUsers = organizationUserDao.findByIdIn(ids);
            if (ObjectUtils.isNotEmpty(orgUsers)) {

                List<DevicePermiss> permisses = new ArrayList<DevicePermiss>();
                for (DeviceInfo deviceInfo : deviceInfos) {
                    for (OrganizationUser organizationUser : orgUsers) {
                        String userId = organizationUser.getUserId();
                        // 判断是否是编辑
                        DevicePermiss permiss = devicePermissDao.findTopByUserIdAndDeviceIdAndProjectOid(userId, deviceInfo.getDeviceId(), projectOid);
                        if (ObjectUtils.isEmpty(permiss)) {
                            permiss = new DevicePermiss();
                            initEntity(permiss);
                        } else {
                            initUpdateEntity(permiss);
                        }
                        buildDeviceInfo(permiss, deviceInfo);
                        buildOrgUserInfo(permiss, organizationUser);
                        permisses.add(permiss);
                    }
                }
                devicePermissDao.saveAll(permisses);
                // 下发设备权限增加数据
                devicePermissIotService.changeDeviceUser(permisses, 1, "");

                // 因为是新增加，下发关联的用户信息
                devicePermissIotService.changeUserInfo(permisses, 1);
            }
        }
        return ResultContent.buildSuccess();
    }

    private void buildDeviceInfo(DevicePermiss permiss, DeviceInfo deviceInfo) {
        if (ObjectUtils.isNotEmpty(deviceInfo)) {
            permiss.setDeviceInfo(deviceInfo);
            permiss.setDeviceId(deviceInfo.getDeviceId());
            permiss.setGateWayId(deviceInfo.getGateWayId());
            permiss.setDeviceName(deviceInfo.getDeviceName());
            permiss.setDeviceType(deviceInfo.getDeviceType());
            permiss.setOnLineState(deviceInfo.getOnLineState());
            permiss.setArea(deviceInfo.getArea());
            permiss.setAreaPaths(deviceInfo.getAreaPaths());
        }
    }

    private void buildOrgUserInfo(DevicePermiss permiss, OrganizationUser organizationUser) {
        if (ObjectUtils.isNotEmpty(organizationUser)) {
            UserAccount userAccount = organizationUser.getUser();
            permiss.setOrganizationUser(organizationUser);
            permiss.setUserAccount(userAccount);

            permiss.setUserId(userAccount.getUserId());
            permiss.setName(userAccount.getName());
            permiss.setDepartment(organizationUser.getDepartment());
            permiss.setRoles(organizationUser.getRoles());
            permiss.setPosition(organizationUser.getPosition());
            permiss.setState(organizationUser.getState());
            permiss.setUserOid(organizationUser.getOid());
            permiss.setCode(organizationUser.getCode());
            permiss.setAuthType(organizationUser.getAuthType());
            permiss.setProjectOid(organizationUser.getProjectOid());
        }
    }

    /**
     * 机构用户信息发送变化
     *
     * @param event
     */
    @EventListener(classes = OrgUserBindUpdateSyncEvent.class)
    @Async
    @SneakyThrows
    public void syncOrgUserChangeInfo(OrgUserBindUpdateSyncEvent event) {
        executorService.execute(() -> {
            log.info("机构用户信息发生变化 syncOrgUserChangeInfo...");

            // 机构用户改变类型
            DataOperationType dataOperationType = event.getDataOperationType();
            // 机构用户数据ID
            List<String> organizationUserIds = event.getOrganizationUserIds();
            if (dataOperationType != null) {
                List<OrganizationUser> organizationUsers = organizationUserDao.findByIdIn(organizationUserIds);
                if (ObjectUtils.isNotEmpty(organizationUsers)) {
                    List<DevicePermiss> list = devicePermissDao.findByOrganizationUserIn(organizationUsers);
                    if (ObjectUtils.isEmpty(list)) {
                        return;
                    }
                    String projectOid = organizationUsers.get(0).getProjectOid();
                    if (dataOperationType == DataOperationType.Update) {
                        for (DevicePermiss permiss : list) {
                            buildOrgUserInfo(permiss, permiss.getOrganizationUser());
                        }
                        devicePermissDao.saveAll(list);
                        // 通知权限下发用户信息 编辑
                        List<String> userIds = organizationUsers.stream().map(OrganizationUser::getUserId).distinct().collect(Collectors.toList());
                        devicePermissEventService.sendUserInfoChangeEvent(userIds, projectOid, "syncOrgUserChangeInfo");
                    } else if (dataOperationType == DataOperationType.Delete) {
                        // 下发移除权限
                        devicePermissIotService.changeDeviceUser(list, 0, "");
                        // 删除
                        devicePermissDao.deleteAll(list);
                    }
                }
            }
        });
    }


    /**
     * 分页数据
     *
     * @param param
     * @param pageable
     * @return
     */
    public ResultContent<Page<DevicePermissModel>> page(DevicePermissSearch param, Pageable pageable) {
        String projectOid = param.getProjectOid();
        Organization organization = organizationDao.findTopByOid(projectOid);
        if (ObjectUtils.isEmpty(organization)) {
            return ResultContent.buildFail("projectOid不存在");
        }
        Page<DevicePermiss> page = devicePermissDao.page(pageable, param);
        return ResultContent.buildSuccess(PageEntityUtil.concurrent2PageModel(page, this::toModel));
    }

    public ResultContent<DevicePermissModel> getDetail(String id) {
        DevicePermiss entity = devicePermissDao.findTopById(id);
        if (ObjectUtils.isEmpty(entity)) {
            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, id));
        }
        return ResultContent.buildSuccess(toModel(entity));
    }

    /**
     * 改变状态
     *
     * @param id
     * @param dataState
     * @return
     */
    public ResultContent changeState(String id, DataState dataState) {
        DevicePermiss entity = devicePermissDao.findTopById(id);
        if (ObjectUtils.isEmpty(entity)) {
            return ResultContent.buildFail(String.format(ResultMessage.DATA_NOT_EXIST, id));
        }
        entity.setDataState(dataState);
        devicePermissDao.save(entity);
        String groupId = CommonUtil.UUID();
        if (dataState == DataState.Disable) {
            // 移除权限
            devicePermissIotService.changeDeviceUser(List.of(entity), 0, groupId);
        } else {
            // 启用
            devicePermissIotService.changeDeviceUser(List.of(entity), 1, groupId);
        }
        return ResultContent.buildSuccess();
    }

    /**
     * 删除多个
     *
     * @param param
     * @return
     */
    public ResultContent deleteByIds(IDsParam param) {
        if (ObjectUtils.isNotEmpty(param.getIds())) {
            List<DevicePermiss> list = devicePermissDao.findByIdIn(param.getIds());
            // 1: 移除权限
            devicePermissIotService.changeDeviceUser(list, 0, "");
            // 2：删除数据
            devicePermissDao.deleteAll(list);
        }
        return ResultContent.buildSuccess();
    }

    /**
     * 查询用户ID关联的设备数据
     *
     * @param projectOid
     * @param userIds
     * @return
     */
    public List<String> getUserAllDeviceIds(String projectOid, List<String> userIds) {
        List<String> deviceIds = Lists.newArrayList();
        if (StringUtils.isNotEmpty(projectOid) && ObjectUtils.isNotEmpty(userIds)) {
            List<DevicePermiss> list = devicePermissDao.findByUserIdInAndProjectOidAndDataState(userIds, projectOid, DataState.Enable);
            if (ObjectUtils.isNotEmpty(list)) {
                deviceIds = list.stream().map(it -> it.getDeviceId()).collect(Collectors.toList());
            }
        }
        return deviceIds;
    }

    public DevicePermissModel toModel(DevicePermiss entity) {
        DevicePermissModel model = null;
        if (ObjectUtils.isNotEmpty(entity)) {
            model = new DevicePermissModel();
            BeanUtils.copyProperties(entity, model);

            model.setDeviceInfo(deviceInfoService.toModel(entity.getDeviceInfo()));

            OrganizationUserModel organizationUser = userAccountService.toOrgUserModel(entity.getOrganizationUser());
            model.setOrganizationUser(organizationUser);
            if (ObjectUtils.isNotEmpty(organizationUser)) {
                model.setPosition(organizationUser.getPosition());
                model.setRoles(organizationUser.getRoles());
                model.setDepartment(organizationUser.getDepartment());
                model.setState(organizationUser.getState());
            }
        }
        return model;
    }

}
