package com.lesingle.creation.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lesingle.creation.common.exception.BusinessException;
import com.lesingle.creation.dto.role.CreateRoleDTO;
import com.lesingle.creation.dto.role.UpdateRoleDTO;
import com.lesingle.creation.entity.Role;
import com.lesingle.creation.entity.RolePermission;
import com.lesingle.creation.mapper.RoleMapper;
import com.lesingle.creation.mapper.RolePermissionMapper;
import com.lesingle.creation.service.RoleService;
import com.lesingle.creation.vo.role.RoleDetailVO;
import com.lesingle.creation.vo.role.RoleListVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 角色服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements RoleService {

    private final RoleMapper roleMapper;
    private final RolePermissionMapper rolePermissionMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RoleDetailVO create(CreateRoleDTO dto, Long tenantId, Long operatorId) {
        log.info("开始创建角色，角色编码：{}", dto.getCode());

        // 检查角色编码是否已存在
        Role existingRole = roleMapper.selectByCode(tenantId, dto.getCode());
        if (existingRole != null) {
            throw new BusinessException("角色编码已存在");
        }

        // 创建角色
        Role role = new Role();
        role.setTenantId(tenantId);
        role.setName(dto.getName());
        role.setCode(dto.getCode());
        role.setDescription(dto.getDescription());
        role.setValidState(1);
        role.setCreateBy(String.valueOf(operatorId));

        roleMapper.insert(role);
        log.info("角色创建成功，角色 ID: {}", role.getId());

        // 如果提供了权限 ID，创建权限关联
        if (!CollectionUtils.isEmpty(dto.getPermissionIds())) {
            List<RolePermission> rolePermissions = dto.getPermissionIds().stream()
                    .map(permissionId -> {
                        RolePermission rp = new RolePermission();
                        rp.setRoleId(role.getId());
                        rp.setPermissionId(permissionId);
                        return rp;
                    })
                    .collect(Collectors.toList());
            rolePermissionMapper.saveBatch(rolePermissions);
            log.info("角色权限关联创建成功，权限数量：{}", dto.getPermissionIds().size());
        }

        return convertToDetailVO(role);
    }

    @Override
    public Page<RoleListVO> pageList(Long tenantId, int page, int pageSize) {
        log.info("分页查询角色列表，租户 ID: {}, 页码：{}, 每页大小：{}", tenantId, page, pageSize);

        Page<Role> rolePage = new Page<>(page, pageSize);
        LambdaQueryWrapper<Role> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Role::getTenantId, tenantId)
                .eq(Role::getValidState, 1)
                .orderByDesc(Role::getCreateTime);

        Page<Role> resultPage = roleMapper.selectPage(rolePage, wrapper);

        // 转换为 VO
        List<RoleListVO> voList = resultPage.getRecords().stream()
                .map(this::convertToListVO)
                .collect(Collectors.toList());

        Page<RoleListVO> voPage = new Page<>(resultPage.getCurrent(), resultPage.getSize(), resultPage.getTotal());
        voPage.setRecords(voList);

        return voPage;
    }

    @Override
    public RoleDetailVO detail(Long id) {
        log.info("查询角色详情，角色 ID: {}", id);

        Role role = roleMapper.selectById(id);
        if (role == null) {
            throw new BusinessException("角色不存在");
        }

        return convertToDetailVO(role);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RoleDetailVO update(Long id, UpdateRoleDTO dto, Long tenantId) {
        log.info("更新角色，角色 ID: {}", id);

        Role existingRole = roleMapper.selectById(id);
        if (existingRole == null) {
            throw new BusinessException("角色不存在");
        }

        // 如果更新了 code，检查是否冲突
        if (dto.getCode() != null && !dto.getCode().isEmpty()) {
            Role conflictRole = roleMapper.selectByCodeExclude(tenantId, dto.getCode(), id);
            if (conflictRole != null) {
                throw new BusinessException("角色编码已存在");
            }
        }

        // 更新角色信息
        Role role = new Role();
        role.setId(id);
        role.setName(dto.getName());
        role.setCode(dto.getCode());
        role.setDescription(dto.getDescription());

        roleMapper.updateById(role);
        log.info("角色更新成功，角色 ID: {}", id);

        // 如果提供了 permissionIds，更新权限关联
        if (dto.getPermissionIds() != null) {
            // 先删除现有权限关联
            LambdaQueryWrapper<RolePermission> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(RolePermission::getRoleId, id);
            rolePermissionMapper.delete(wrapper);
            log.info("已删除角色原有权限关联");

            // 创建新的权限关联
            if (!dto.getPermissionIds().isEmpty()) {
                List<RolePermission> rolePermissions = dto.getPermissionIds().stream()
                        .map(permissionId -> {
                            RolePermission rp = new RolePermission();
                            rp.setRoleId(id);
                            rp.setPermissionId(permissionId);
                            return rp;
                        })
                        .collect(Collectors.toList());
                rolePermissionMapper.saveBatch(rolePermissions);
                log.info("角色新权限关联创建成功，权限数量：{}", dto.getPermissionIds().size());
            }
        }

        return convertToDetailVO(roleMapper.selectById(id));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Long id) {
        log.info("删除角色，角色 ID: {}", id);

        Role role = roleMapper.selectById(id);
        if (role == null) {
            throw new BusinessException("角色不存在");
        }

        // 删除角色关联
        LambdaQueryWrapper<RolePermission> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(RolePermission::getRoleId, id);
        rolePermissionMapper.delete(wrapper);

        // 删除角色（逻辑删除）
        roleMapper.deleteById(id);
        log.info("角色删除成功，角色 ID: {}", id);
    }

    @Override
    public List<RoleListVO> list(Long tenantId) {
        log.info("查询角色列表，租户 ID: {}", tenantId);

        LambdaQueryWrapper<Role> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Role::getTenantId, tenantId)
                .eq(Role::getValidState, 1)
                .orderByAsc(Role::getCode);

        List<Role> roles = roleMapper.selectList(wrapper);

        return roles.stream()
                .map(this::convertToListVO)
                .collect(Collectors.toList());
    }

    /**
     * 转换为详情 VO
     */
    private RoleDetailVO convertToDetailVO(Role role) {
        RoleDetailVO vo = new RoleDetailVO();
        vo.setId(role.getId());
        vo.setTenantId(role.getTenantId());
        vo.setName(role.getName());
        vo.setCode(role.getCode());
        vo.setDescription(role.getDescription());
        vo.setValidState(role.getValidState());
        vo.setCreateBy(role.getCreateBy());
        vo.setCreateTime(role.getCreateTime());
        vo.setUpdateBy(role.getUpdateBy());
        vo.setUpdateTime(role.getUpdateTime());

        // TODO: 获取角色权限
        vo.setPermissionIds(new ArrayList<>());
        vo.setPermissionNames(new ArrayList<>());

        return vo;
    }

    /**
     * 转换为列表 VO
     */
    private RoleListVO convertToListVO(Role role) {
        RoleListVO vo = new RoleListVO();
        vo.setId(role.getId());
        vo.setTenantId(role.getTenantId());
        vo.setName(role.getName());
        vo.setCode(role.getCode());
        vo.setDescription(role.getDescription());
        vo.setValidState(role.getValidState());
        vo.setCreateTime(role.getCreateTime());

        return vo;
    }
}
