package com.jwipc.sys.logic.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Pair;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.jwipc.constant.EnableStatus;
import com.jwipc.exception.DaoException;
import com.jwipc.page.PageUtil;
import com.jwipc.page.PageView;
import com.jwipc.sys.constant.MenuType;
import com.jwipc.sys.constant.ResourceHideStatus;
import com.jwipc.sys.constant.SupplierRoleType;
import com.jwipc.sys.convert.ButtonConvert;
import com.jwipc.sys.convert.RoleConvert;
import com.jwipc.sys.dto.*;
import com.jwipc.sys.entity.*;
import com.jwipc.sys.logic.RoleLogic;
import com.jwipc.sys.model.query.RoleListQuery;
import com.jwipc.sys.service.*;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;


/**
 * <p> </p>
 *
 * @author BOGON
 * @version 1.0
 * @since JDK 1.8
 */
@Service
@RequiredArgsConstructor
public class RoleLogicImpl implements RoleLogic {
    private final IRoleService roleService;
    private final RoleConvert roleConvert;
    private final IRoleResService roleResService;
    private final IRoleResButtonService roleResButtonService;
    private final IButtonService buttonService;
    private final IResourcesService resourcesService;
    private final ButtonConvert buttonConvert;
    private final IDealtWithTargetRoleService dealtWithTargetRoleService;
    private final IUserRoleService userRoleService;

    @Override
    public PageView getList(RoleListQuery query) {
        final Page<Role> page = PageUtil.toPage(query);
        final LambdaQueryWrapper<Role> queryWrapper = new LambdaQueryWrapper<Role>().eq(Role::getIsvalid,
                        EnableStatus.ENABLE.getStatus())
                .eq(Objects.nonNull(query.getType()), Role::getType, query.getType())
                .like(StrUtil.isNotEmpty(query.getName()), Role::getName, query.getName());
        final List<Role> list = roleService.list(page, queryWrapper);
        List<RoleListDTO> roleListDTOS = roleConvert.entities2ListDTOs(list);
        return PageUtil.getPV(roleListDTOS, page.getTotal());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void save(RoleAddDTO roleAddDTO) {
        Role role = roleConvert.addDTO2Entity(roleAddDTO);
        final LambdaQueryWrapper<Role> queryWrapper = new LambdaQueryWrapper<Role>().eq(Role::getRolekey,
                roleAddDTO.getRolekey());
        final List<Role> list = roleService.list(queryWrapper);
        if (CollUtil.isNotEmpty(list)) {
            throw new DaoException("角色重复");
        }
        roleService.save(role);
    }

    @Override
    public RoleEditDTO getForEdit(Long id) {
        final Role byId = roleService.getById(id);
        return roleConvert.entity2EditDTO(byId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(RoleEditDTO roleEditDTO) {
        Role role = roleConvert.editDTO2entity(roleEditDTO);
        roleService.updateById(role);
    }

    @Override
    public Pair<List<String>, List<String>> getForPermissions(Long id) {
        final List<RoleRes> list = roleResService.list(new LambdaQueryWrapper<RoleRes>().eq(RoleRes::getRoleId, id));
        List<String> resourceIds = Lists.newArrayList();
        if (CollUtil.isNotEmpty(list)) {
            resourceIds.addAll(list.stream().map(RoleRes::getResId).map(String::valueOf).collect(Collectors.toList()));
        }
        final List<RoleResButton> roleResButtons = roleResButtonService.list(
                new LambdaQueryWrapper<RoleResButton>().eq(RoleResButton::getRoleId, id));
        List<String> buttonIds = Lists.newArrayList();
        if (CollUtil.isNotEmpty(roleResButtons)) {
            buttonIds.addAll(roleResButtons.stream().map(RoleResButton::getButtonId).map(String::valueOf)
                    .collect(Collectors.toList()));
        }
        return Pair.of(resourceIds, buttonIds);
    }

    @Override
    public List<RolePermTreeDTO> getPermissionGrid(int type) {
        final List<Resources> resources = resourcesService.list(
                new LambdaQueryWrapper<Resources>().eq(Resources::getHideFlag, ResourceHideStatus.SHOW.getFlag())
                        .eq(Resources::getMenuType, type));
        List<RolePermTreeDTO> list = Lists.newArrayList();
        for (Resources resource : resources) {
            RolePermTreeDTO rolePermTreeDTO = new RolePermTreeDTO();
            rolePermTreeDTO.setId(resource.getId());
            rolePermTreeDTO.setText(resource.getName());
            rolePermTreeDTO.setCode(resource.getResKey());
            rolePermTreeDTO.setParentId(resource.getParentId());
            rolePermTreeDTO.setButtons(Lists.newArrayList());
            list.add(rolePermTreeDTO);
        }
        final Map<Long, RolePermTreeDTO> resMap = list.stream()
                .collect(Collectors.toMap(RolePermTreeDTO::getId, a -> a));
        final List<Button> buttons = buttonService.list();
        for (Button button : buttons) {
            if (Objects.nonNull(button.getResourceId())) {
                final RolePermTreeDTO rolePermTreeDTO = resMap.get(button.getResourceId());
                if (Objects.nonNull(rolePermTreeDTO)) {
                    rolePermTreeDTO.getButtons().add(buttonConvert.entity2DTO(button));
                }
            }
        }
        return list;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePermission(UpdatePermissionDTO updatePermissionDTO) {
        //先删除 资源分配表 按钮分配表里面已有的数据
        final Integer menuType = updatePermissionDTO.getMenuType();
        final Long roleId = updatePermissionDTO.getRoleId();
        roleResService.removeByRoleIdAndMenuType(roleId, menuType);
        if (menuType.compareTo(MenuType.MENU_PC.getType()) == 0) {
            roleResButtonService.remove(new LambdaQueryWrapper<RoleResButton>().eq(RoleResButton::getRoleId, roleId));
        }
        //将分配的菜单资源保存
        final List<Long> resList = updatePermissionDTO.getResources();
        if (CollUtil.isNotEmpty(resList)) {
            final List<RoleRes> roleResList = Lists.newArrayList();
            resList.forEach(e -> {
                final RoleRes res = new RoleRes();
                res.setRoleId(roleId);
                res.setResId(e);
                roleResList.add(res);
            });


            roleResService.saveBatch(roleResList);
            if (menuType.compareTo(MenuType.MENU_PC.getType()) == 0) {
                //按钮资源比菜单资源低一级，等菜单资源保存之后再保存
                final List<ButtonDTO> buttonList = updatePermissionDTO.getButtons();
                if (CollUtil.isNotEmpty(buttonList)) {
                    final List<RoleResButton> resButtonList = Lists.newArrayList();
                    buttonList.forEach(e -> {
                        final RoleResButton resButton = new RoleResButton();
                        resButton.setRoleId(roleId);
                        resButton.setButtonId(e.getId());
                        resButton.setResId(e.getResourceId());
                        resButtonList.add(resButton);
                    });
                    roleResButtonService.saveBatch(resButtonList);
                }
            }
        }
    }

    @Override
    public List<Long> getDealtConfig(Long id) {
        final List<DealtWithTargetRole> list = dealtWithTargetRoleService.list(
                new LambdaQueryWrapper<DealtWithTargetRole>().eq(DealtWithTargetRole::getRoleId, id));
        return list.stream().map(DealtWithTargetRole::getTargetInfoId).collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateDealtConfig(DealtWithTargetRoleUpdateDTO updatePermissionDTO) {
        if (updatePermissionDTO.getRoleId() == null) {
            throw new DaoException("参数错误,角色id不能为空!");
        }
        final String roleId = updatePermissionDTO.getRoleId().toString();
        Role role = roleService.getById(roleId);
        if (role == null) {
            throw new DaoException("未找到角色!");
        }

        dealtWithTargetRoleService.remove(
                new LambdaQueryWrapper<DealtWithTargetRole>().eq(DealtWithTargetRole::getRoleId, roleId));

        List<DealtWithTargetRole> targetRoleList = Lists.newArrayList();

        if (CollUtil.isNotEmpty(updatePermissionDTO.getTargetInfoIds())) {
            for (Long targetInfoId : updatePermissionDTO.getTargetInfoIds()) {
                DealtWithTargetRole dealtWithTargetRole = new DealtWithTargetRole();
                dealtWithTargetRole.setRoleId(Long.valueOf(roleId));
                dealtWithTargetRole.setTargetInfoId(targetInfoId);
                targetRoleList.add(dealtWithTargetRole);
            }
        }
        if (targetRoleList.size() > 0) {
            dealtWithTargetRoleService.saveBatch(targetRoleList);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void remove(Long id) {
        //角色删除，需要删除关联表
        //dealt_with_target_role
        //sp_role
        //sp_role_res
        //sp_role_res_button
        //sp_user_role
        //需要判断是否存在用户是用这个角色，如果有就无法删除
        final List<UserRole> list = userRoleService.list(
                new LambdaQueryWrapper<UserRole>().eq(UserRole::getRoleId, id));
        if (CollUtil.isNotEmpty(list)) {
            throw new DaoException("角色正在被使用无法删除!");
        }
        dealtWithTargetRoleService.remove(
                new LambdaQueryWrapper<DealtWithTargetRole>().eq(DealtWithTargetRole::getRoleId, id));
        roleResService.remove(new LambdaQueryWrapper<RoleRes>().eq(RoleRes::getRoleId, id));
        roleResButtonService.remove(new LambdaQueryWrapper<RoleResButton>().eq(RoleResButton::getRoleId, id));
        roleService.removeById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createSupplierDefaultRole(Long userId) {
        UserRole userRole = new UserRole();
        userRole.setUserId(userId);
        //查询供应商默认角色
        final Role role = roleService.getOne(
                new LambdaQueryWrapper<Role>().eq(Role::getRolekey, SupplierRoleType.default_role.getCode()), false);
        if (Objects.isNull(role)) {
            throw new DaoException("供应商默认角色不存在!");
        }
        userRole.setRoleId(role.getId());
        userRoleService.save(userRole);
    }

    @Override
    public List<RoleListDTO> getUserRoles(Long id) {
        List<Role> userRoles = roleService.getUserRoles(id);
        if(CollUtil.isNotEmpty(userRoles)){
            List<RoleListDTO> roleListDTOS = roleConvert.entities2ListDTOs(userRoles);
            return roleListDTOS;
        }
        return null;
    }
}