package com.seer.teach.user.admin.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.seer.teach.common.PageListBean;
import com.seer.teach.common.enums.ResultCodeEnum;
import com.seer.teach.common.exception.CommonException;
import com.seer.teach.common.utils.AssertUtils;
import com.seer.teach.common.utils.PageConverterUtils;
import com.seer.teach.user.admin.convert.AdminAuthorityConvert;
import com.seer.teach.user.admin.convert.AdminUserConvert;
import com.seer.teach.user.admin.convert.RoleConvert;
import com.seer.teach.user.admin.request.AddAuthority;
import com.seer.teach.user.admin.request.AuthorityBatchUpdate;
import com.seer.teach.user.admin.request.UpdateAuthority;
import com.seer.teach.user.admin.response.AdminUserInfoResp;
import com.seer.teach.user.admin.response.AuthorityRespData;
import com.seer.teach.user.admin.response.RoleResp;
import com.seer.teach.user.admin.service.AdminAuthorityService;
import com.seer.teach.user.entity.AuthorityEntity;
import com.seer.teach.user.entity.RoleAuthorityEntity;
import com.seer.teach.user.entity.RoleEntity;
import com.seer.teach.user.entity.UserEntity;
import com.seer.teach.user.entity.UserRoleEntity;
import com.seer.teach.user.service.IAuthorityService;
import com.seer.teach.user.service.IRoleAuthorityService;
import com.seer.teach.user.service.IRoleService;
import com.seer.teach.user.service.IUserRoleService;
import com.seer.teach.user.service.IUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;

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

/**
 * @Author: Captain
 * @Description:
 * @Date: 2025-06-23 22:06
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AdminAuthorityServiceImpl implements AdminAuthorityService {

    private final IUserService userService;

    private final IUserRoleService userRoleService;

    private final IRoleAuthorityService roleAuthorityService;

    private final IAuthorityService authorityService;

    private final IRoleService roleService;

    @Override
    public List<AuthorityRespData> getSystemAllAuthority() {
        List<AuthorityEntity> authorityData = authorityService.list();
        if (CollectionUtils.isEmpty(authorityData)) {
            return Collections.emptyList();
        }
        return getAuthorityRespData(authorityData);
    }

    private List<AuthorityRespData> getAuthorityRespData(List<AuthorityEntity> authorityData) {
        Set<Integer> allIds = authorityData.stream()
                .map(AuthorityEntity::getId)
                .collect(Collectors.toSet());

        Map<Integer, List<AuthorityEntity>> authorityMap = authorityData.stream().collect(Collectors.groupingBy(AuthorityEntity::getPid));

        List<AuthorityEntity> rootAuthorities = authorityData.stream()
                .filter(entity -> entity.getPid() == null || !allIds.contains(entity.getPid()))
                .collect(Collectors.toList());

        if (CollectionUtils.isEmpty(rootAuthorities)) {
            return Collections.emptyList();
        }

        List<AuthorityRespData> result  = AdminAuthorityConvert.INSTANCE.toAuthorityRespData(rootAuthorities);
        result.forEach(authority -> buildChildren(authority, authorityMap));
        sortAuthorityList(result );
        return result ;
    }

    private void buildChildren(AuthorityRespData parentAuthority,
                               Map<Integer, List<AuthorityEntity>> authorityMap) {
        List<AuthorityEntity> childrenEntities = authorityMap.get(parentAuthority.getId());
        if (CollectionUtils.isEmpty(childrenEntities)) {
            return;
        }

        List<AuthorityRespData> children = AdminAuthorityConvert.INSTANCE.toAuthorityRespData(childrenEntities);
        parentAuthority.setChildren(children);
        children.forEach(child -> buildChildren(child, authorityMap));
    }


    public void sortAuthorityList(List<AuthorityRespData> authorityList) {
        if (CollectionUtils.isEmpty(authorityList)) {
            return;
        }

        authorityList.sort(Comparator.comparing(
                authority -> authority.getSort() != null ? authority.getSort() : Integer.MAX_VALUE,
                Comparator.nullsFirst(Comparator.naturalOrder())
        ));

        authorityList.stream()
                .filter(authority -> !CollectionUtils.isEmpty(authority.getChildren()))
                .forEach(authority -> sortAuthorityList(authority.getChildren()));
    }

    @Override
    public void addSystemAuthority(AddAuthority params) {
        AuthorityEntity authorityEntity = AdminAuthorityConvert.INSTANCE.toEntity(params);
        boolean save = authorityService.save(authorityEntity);
        log.info("保存权限数据：{}", save);
    }

    @Override
    public void deleteAuthorityById(Integer id) {
        long count = roleAuthorityService.count(new LambdaQueryWrapper<RoleAuthorityEntity>()
                .eq(RoleAuthorityEntity::getAuthorityId, id));
        if (count > 0) {
            throw new CommonException(ResultCodeEnum.THE_AUTHORITY_IS_USED);
        }
        List<AuthorityEntity> authorityData = authorityService.list(new LambdaQueryWrapper<AuthorityEntity>()
                .eq(AuthorityEntity::getPid, id));
        if (CollectionUtils.isNotEmpty(authorityData)) {
            throw new CommonException(ResultCodeEnum.THE_AUTHORITY_HAS_CHILDREN_AUTHORITY);
        }
        authorityService.removeById(id);
    }


    @Override
    public void updateAuthority(UpdateAuthority params) {
        AuthorityEntity authorityEntity = AdminAuthorityConvert.INSTANCE.toEntity(params);
        authorityService.updateById(authorityEntity);
    }

    /**
     * 分页查询权限列表
     *
     * @param page
     * @param size
     * @param authorityName
     * @return
     */
    @Override
    public PageListBean<AuthorityRespData> getAuthorityPage(Integer page, Integer size, String authorityName) {
        Page<AuthorityEntity> pageParm = new Page<>(page, size);
        LambdaQueryWrapper<AuthorityEntity> wrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotBlank(authorityName)) {
            wrapper.like(AuthorityEntity::getAuthorityCode, authorityName);
        }
        Page<AuthorityEntity> resultPage = authorityService.page(pageParm, wrapper);

        return PageConverterUtils.convertPageListBean(resultPage, AdminAuthorityConvert.INSTANCE::toAuthorityRespData);
    }

    @Override
    public AdminUserInfoResp info(int loginUserId,String module) {
        List<RoleResp> roleRespList =  new ArrayList<>();

        UserEntity userEntity = userService.getOne(new LambdaQueryWrapper<UserEntity>().eq(UserEntity::getId, loginUserId));
        List<UserRoleEntity> data = userRoleService.list(new LambdaQueryWrapper<UserRoleEntity>().eq(UserRoleEntity::getUserId, loginUserId));
        if (CollectionUtil.isEmpty(data)) {
            return new AdminUserInfoResp(roleRespList, userEntity.getUserName(), Collections.emptyList());
        }
        Set<Integer> roleIds = data.stream().map(UserRoleEntity::getRoleId).collect(Collectors.toSet());
        Collection<RoleEntity> roles = roleService.getRoleListByRoleIds(roleIds);

        List<RoleAuthorityEntity> roleAuthorityEntities = roleAuthorityService.list(new LambdaQueryWrapper<>(RoleAuthorityEntity.class).in(RoleAuthorityEntity::getRoleId, roleIds));
        if (CollectionUtil.isEmpty(roleAuthorityEntities)) {
            return new AdminUserInfoResp(roleRespList, userEntity.getUserName(), Collections.emptyList());
        }
        Set<Integer> authorityIds = roleAuthorityEntities.stream().map(RoleAuthorityEntity::getAuthorityId).collect(Collectors.toSet());
        List<AuthorityEntity> authorityEntities = authorityService.getListByIdsAndModule(authorityIds, module);
        List<AuthorityEntity> menus = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(authorityEntities)) {
            menus.addAll(authorityEntities);
        }
        List<AuthorityRespData> authorityRespData = getAuthorityRespData(menus);
        return AdminUserConvert.INSTANCE.toInfoResp(userEntity, roles, authorityRespData);
    }

    @Override
    public boolean batchUpdateAuthority(AuthorityBatchUpdate batchUpdateParams) {
        List<AuthorityEntity> authorityEntities = batchUpdateParams.getIds().stream()
                .map(id -> AdminAuthorityConvert.INSTANCE.toEntity(batchUpdateParams, id))
                .collect(Collectors.toList());
        log.info("批量更新权限数据：{}", authorityEntities);
        return authorityService.updateBatchById(authorityEntities);
    }

    @Override
    public boolean toggleShowAuthority(Integer id, Integer isShow) {
        AuthorityEntity authority = authorityService.getById(id);
        AssertUtils.notNull(authority, ResultCodeEnum.AUTHORITY_NOT_FOUND);
        return authorityService.update(new LambdaUpdateWrapper<>(AuthorityEntity.class)
                .eq(AuthorityEntity::getId, id)
                .set(AuthorityEntity::getHidden, isShow));
    }
}