package com.cmeeting.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cmeeting.constant.CategoryConstant;
import com.cmeeting.constant.PermissionPruposeType;
import com.cmeeting.constant.RecordTemplateConstant;
import com.cmeeting.constant.UserTypeConstant;
import com.cmeeting.dto.PermissionCheckedDTO;
import com.cmeeting.exception.RobotBaseException;
import com.cmeeting.mapper.primary.ModulePermissionMapper;
import com.cmeeting.pojo.ModulePermission;
import com.cmeeting.service.ModulePermissionService;
import com.cmeeting.service.SysUserSyncService;
import com.cmeeting.vo.AuthVO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Administrator
 * @description 针对表【module_permission(权限表)】的数据库操作Service实现
 * @createDate 2025-07-17 10:55:32
 */
@Service
public class ModulePermissionServiceImpl extends ServiceImpl<ModulePermissionMapper, ModulePermission>
        implements ModulePermissionService {

    @Resource
    private SysUserSyncService iSysUserSyncService;

    @Override
    public PermissionCheckedDTO permissionList(String search, String categoryId, Integer userType, Integer purpose, Integer targetId, List<String> categoryIdList, List<String> userIdList) {
        PermissionCheckedDTO dto = permissionList(search, categoryId, userType, purpose, categoryIdList, userIdList);
        List<ModulePermission> permissions = baseMapper.selectList(new LambdaQueryWrapper<ModulePermission>()
                .eq(ModulePermission::getUserType, userType)
                .eq(ModulePermission::getPurpose, purpose)
                .eq(targetId != null, ModulePermission::getTargetId, targetId)
                .select(ModulePermission::getRelId, ModulePermission::getType)
        );
        if (CollUtil.isNotEmpty(permissions)) {
            Set<String> deptIds = permissions.stream()
                    .filter(e -> e.getType().equals(RecordTemplateConstant.REL_TYPE_DEPT))
                    .map(ModulePermission::getRelId).collect(Collectors.toSet());
            Set<String> userIds = permissions.stream().filter(e -> e.getType().equals(RecordTemplateConstant.REL_TYPE_USER))
                    .map(ModulePermission::getRelId).collect(Collectors.toSet());
            // 授权了所有人
            boolean all = userIds.contains(CategoryConstant.ALL_EN) || deptIds.contains(CategoryConstant.ALL_EN);
            List<PermissionCheckedDTO.Category> categoryList = dto.getCategoryList();
            if (CollUtil.isNotEmpty(deptIds) && CollUtil.isNotEmpty(categoryList)) {
                for (PermissionCheckedDTO.Category category : categoryList) {
                    if (all || deptIds.contains(category.getId())) {
                        category.setCheck(true);
                    }
                }
            }

            List<PermissionCheckedDTO.User> userList = dto.getUserList();
            if (CollUtil.isNotEmpty(userIds) && CollUtil.isNotEmpty(userList)) {
                for (PermissionCheckedDTO.User user : userList) {
                    if (all || userIds.contains(user.getId())) {
                        user.setCheck(true);
                    }
                }
            }
        }
        return dto;
    }

    @Override
    public PermissionCheckedDTO permissionList(String search, String categoryId, Integer userType, Integer purpose, List<String> categoryList, List<String> userList) {
        return iSysUserSyncService.listByCategoryId(categoryId, search, categoryList, userList);
    }

    @Override
    public List<PermissionCheckedDTO.CateOrUser> checkedList(String search, Integer purpose, Long targetId) {
        List<PermissionCheckedDTO.CateOrUser> retList = new ArrayList<>();
        List<ModulePermission> modulePermissions = baseMapper.selectList(new LambdaQueryWrapper<ModulePermission>()
                .eq(ModulePermission::getPurpose, purpose)
                .eq(targetId != null, ModulePermission::getTargetId, targetId)
                .select(ModulePermission::getRelId, ModulePermission::getType)
        );

        if (CollUtil.isNotEmpty(modulePermissions)) {
            List<String> cateIds = modulePermissions.stream().filter(e -> Objects.equals(e.getType(), RecordTemplateConstant.REL_TYPE_DEPT)).map(ModulePermission::getRelId).collect(Collectors.toList());
            List<String> userIds = modulePermissions.stream().filter(e -> Objects.equals(e.getType(), RecordTemplateConstant.REL_TYPE_USER)).map(ModulePermission::getRelId).collect(Collectors.toList());
            Set<String> ids = modulePermissions.stream().map(ModulePermission::getRelId).collect(Collectors.toSet());
            if (CollUtil.isNotEmpty(ids) && ids.contains(CategoryConstant.ALL_EN)) {
                PermissionCheckedDTO.CateOrUser cateOrUser = PermissionCheckedDTO.CateOrUser.builder()
                        .id(CategoryConstant.ALL_EN).name("所有人").deptName("所有人").userType(UserTypeConstant.SYNC).type(RecordTemplateConstant.REL_TYPE_USER).build();
                retList.add(cateOrUser);
                return retList;
            }
            PermissionCheckedDTO permissionCheckedDTO = permissionList(search, null, null, purpose, cateIds, userIds);
            if (CollUtil.isNotEmpty(permissionCheckedDTO.getUserList())) {
                for (PermissionCheckedDTO.User user : permissionCheckedDTO.getUserList()) {
                    if (userIds.contains(user.getId())) {
                        String deptPath = iSysUserSyncService.getDeptPathName("", user.getDeptId());
                        PermissionCheckedDTO.CateOrUser cateOrUser = PermissionCheckedDTO.CateOrUser.builder()
                                .id(user.getId()).name(user.getName()).deptName(deptPath).userType(user.getUserType()).type(RecordTemplateConstant.REL_TYPE_USER).build();
                        retList.add(cateOrUser);
                    }
                }
            }
            if (CollUtil.isNotEmpty(permissionCheckedDTO.getCategoryList())) {
                for (PermissionCheckedDTO.Category category : permissionCheckedDTO.getCategoryList()) {
                    if (cateIds.contains(category.getId())) {
                        String deptPath = iSysUserSyncService.getDeptPathName("", category.getId());
                        PermissionCheckedDTO.CateOrUser cateOrUser = PermissionCheckedDTO.CateOrUser.builder()
                                .id(category.getId()).name(category.getName()).deptName(deptPath).userType(category.getUserType()).type(RecordTemplateConstant.REL_TYPE_DEPT).build();
                        retList.add(cateOrUser);
                    }
                }
            }
        }
        return retList;
    }

    @Override
    public Boolean auth(List<AuthVO.Add> authData) {
        if (CollUtil.isNotEmpty(authData)) {
            List<ModulePermission> list = new ArrayList<>();
            for (AuthVO.Add authDatum : authData) {
                ModulePermission permission = BeanUtil.copyProperties(authDatum, ModulePermission.class);
                permission.setCreateTime(new Date());
                list.add(permission);
            }
            return this.saveBatch(list);
        }
        return false;
    }

    @Override
    public List<PermissionCheckedDTO.User> personalCancelList(String query) {
        List<PermissionCheckedDTO.User> retList = new ArrayList<>();

        List<ModulePermission> modulePermissions = baseMapper.selectList(new LambdaQueryWrapper<ModulePermission>()
                .eq(ModulePermission::getPurpose, PermissionPruposeType.PERSONAL_CLOSE)
                .select(ModulePermission::getRelId)
        );
        if (CollUtil.isNotEmpty(modulePermissions)) {
            List<String> userIds = modulePermissions.stream().map(ModulePermission::getRelId).collect(Collectors.toList());
            PermissionCheckedDTO permissionCheckedDTO = permissionList(null, null, UserTypeConstant.SYNC, PermissionPruposeType.PERSONAL_CLOSE, null, userIds);
            List<PermissionCheckedDTO.User> userList = permissionCheckedDTO.getUserList();
            if (CollUtil.isNotEmpty(userList) && StrUtil.isNotBlank(query)) {
                userList = userList.stream().filter(e -> e.getName().contains(query)).collect(Collectors.toList());
            }
            retList = userList;
        }
        return retList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean personalSwitch(String userId, boolean enable) {
        if (enable) {
            this.remove(new LambdaQueryWrapper<ModulePermission>()
                    .eq(ModulePermission::getType, RecordTemplateConstant.REL_TYPE_USER)
                    .eq(ModulePermission::getPurpose, PermissionPruposeType.PERSONAL_CLOSE)
                    .eq(ModulePermission::getRelId, userId));
            ModulePermission cancel = ModulePermission.builder()
                    .type(RecordTemplateConstant.REL_TYPE_USER)
                    .purpose(PermissionPruposeType.ADMIN_AUTH)
                    .userType(UserTypeConstant.SYNC)
                    .relId(userId)
                    .createTime(new Date()).build();
            return this.save(cancel);
        } else {
            this.remove(new LambdaQueryWrapper<ModulePermission>()
                    .eq(ModulePermission::getType, RecordTemplateConstant.REL_TYPE_USER)
                    .eq(ModulePermission::getPurpose, PermissionPruposeType.ADMIN_AUTH)
                    .eq(ModulePermission::getRelId, userId));
            ModulePermission cancel = ModulePermission.builder()
                    .type(RecordTemplateConstant.REL_TYPE_USER)
                    .purpose(PermissionPruposeType.PERSONAL_CLOSE)
                    .userType(UserTypeConstant.SYNC)
                    .relId(userId)
                    .createTime(new Date()).build();
            return this.save(cancel);
        }
    }

    @Override
    public List<ModulePermission> checkPermission(List<String> deptIds, String userId) {
        return this.list(new LambdaQueryWrapper<ModulePermission>()
                .and(e -> e.eq(CollUtil.isNotEmpty(deptIds), ModulePermission::getType, RecordTemplateConstant.REL_TYPE_DEPT).in(ModulePermission::getRelId, deptIds)
                        .or().eq(ModulePermission::getType, RecordTemplateConstant.REL_TYPE_USER).eq(ModulePermission::getRelId, userId))
                .select(ModulePermission::getTargetId)
        );
    }

    @Override
    public List<Long> checkPermission(List<String> deptIds, String userId, Integer purpose) {
        List<ModulePermission> list = this.list(new LambdaQueryWrapper<ModulePermission>()
                .eq(ModulePermission::getPurpose, purpose)
                .and(e -> e.eq(CollUtil.isNotEmpty(deptIds), ModulePermission::getType, RecordTemplateConstant.REL_TYPE_DEPT).in(ModulePermission::getRelId, deptIds)
                        .or().eq(ModulePermission::getType, RecordTemplateConstant.REL_TYPE_USER).eq(ModulePermission::getRelId, userId)
                        .or().eq(ModulePermission::getType, RecordTemplateConstant.REL_TYPE_USER).eq(ModulePermission::getRelId, CategoryConstant.ALL_EN)
                ).select(ModulePermission::getTargetId)
        );
        return list.stream().map(ModulePermission::getTargetId).collect(Collectors.toList());
    }

    @Override
    public Boolean checkAdminPermission(List<String> deptIds, String userId) {
        List<ModulePermission> list = this.list(new LambdaQueryWrapper<ModulePermission>()
                .eq(ModulePermission::getPurpose, PermissionPruposeType.ADMIN_AUTH)
                .and(e -> e.eq(CollUtil.isNotEmpty(deptIds), ModulePermission::getType, RecordTemplateConstant.REL_TYPE_DEPT).in(CollUtil.isNotEmpty(deptIds), ModulePermission::getRelId, deptIds)
                        .or().eq(ModulePermission::getType, RecordTemplateConstant.REL_TYPE_USER).eq(ModulePermission::getRelId, userId)
                        .or().eq(ModulePermission::getType, RecordTemplateConstant.REL_TYPE_USER).eq(ModulePermission::getRelId, CategoryConstant.ALL_EN)
                ).select(ModulePermission::getId)
        );
        return CollUtil.isNotEmpty(list);
    }

    @Override
    public Boolean checkPermission(List<String> deptIds, String userId, Integer purpose, Long targetId) {
        boolean flag = purpose.equals(PermissionPruposeType.TEMPLATE_TYPE_PERMISSION) || purpose.equals(PermissionPruposeType.TEMPLATE_PERMISSION);
        if (flag && targetId != null) {
            throw new RobotBaseException("param error!");
        }
        return baseMapper.selectCount(new LambdaQueryWrapper<ModulePermission>()
                .eq(ModulePermission::getPurpose, purpose)
                .eq(targetId != null, ModulePermission::getTargetId, targetId)
                .and(e -> e.eq(ModulePermission::getType, RecordTemplateConstant.REL_TYPE_DEPT).in(ModulePermission::getRelId, deptIds)
                        .or().eq(ModulePermission::getType, RecordTemplateConstant.REL_TYPE_USER).eq(ModulePermission::getRelId, userId)
                        .or().eq(ModulePermission::getType, RecordTemplateConstant.REL_TYPE_USER).eq(ModulePermission::getRelId, CategoryConstant.ALL_EN)
                ).select(ModulePermission::getTargetId)) > 0;
    }

    @Override
    public Boolean personalStatus(String userId) {
        Integer count = baseMapper.selectCount(new LambdaQueryWrapper<ModulePermission>()
                .eq(ModulePermission::getType, RecordTemplateConstant.REL_TYPE_USER)
                .eq(ModulePermission::getUserType, UserTypeConstant.SYNC)
                .eq(ModulePermission::getPurpose, PermissionPruposeType.PERSONAL_CLOSE)
                .eq(ModulePermission::getRelId, userId)
        );
        return count == 0;
    }


}




