package cn.novalon.manage.sys.core.service.impl;

import cn.novalon.manage.common.util.StatusConstants;
import cn.novalon.manage.sys.core.domain.SysPermission;
import cn.novalon.manage.sys.core.domain.SysRolePermission;
import cn.novalon.manage.sys.core.repository.ISysPermissionRepository;
import cn.novalon.manage.sys.core.repository.ISysRolePermissionRepository;
import cn.novalon.manage.sys.core.service.ISysPermissionService;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 系统权限服务实现类
 * 
 * @author 张翔
 * @date 2026-03-25
 */
@Service
public class SysPermissionService implements ISysPermissionService {

    private final ISysPermissionRepository permissionRepository;
    private final ISysRolePermissionRepository rolePermissionRepository;

    public SysPermissionService(ISysPermissionRepository permissionRepository, 
                                ISysRolePermissionRepository rolePermissionRepository) {
        this.permissionRepository = permissionRepository;
        this.rolePermissionRepository = rolePermissionRepository;
    }

    @Override
    public Mono<SysPermission> findById(Long id) {
        return permissionRepository.findById(id);
    }

    @Override
    public Flux<SysPermission> findAll() {
        return permissionRepository.findAll();
    }

    @Override
    public Flux<SysPermission> findAll(Sort sort) {
        return permissionRepository.findAll(sort);
    }

    @Override
    public Mono<SysPermission> findByPermissionCode(String permissionCode) {
        return permissionRepository.findByPermissionCode(permissionCode);
    }

    @Override
    public Mono<Long> count() {
        return permissionRepository.count();
    }

    @Override
    public Mono<SysPermission> createPermission(SysPermission permission) {
        permission.setCreatedAt(LocalDateTime.now());
        if (permission.getStatus() == null) {
            permission.setStatus(StatusConstants.ENABLED);
        }
        return permissionRepository.save(permission);
    }

    @Override
    public Mono<SysPermission> updatePermission(SysPermission permission) {
        permission.setUpdatedAt(LocalDateTime.now());
        return permissionRepository.updatePermission(permission);
    }

    @Override
    public Mono<Void> deletePermission(Long id) {
        return permissionRepository.findById(id)
                .flatMap(permission -> {
                    permission.delete();
                    return permissionRepository.updatePermission(permission)
                            .then(rolePermissionRepository.deleteByPermissionId(id));
                });
    }

    @Override
    public Mono<Boolean> existsByPermissionCode(String permissionCode) {
        return permissionRepository.existsByPermissionCode(permissionCode);
    }

    @Override
    public Flux<SysPermission> findByRoleId(Long roleId) {
        return permissionRepository.findByRoleId(roleId);
    }

    @Override
    public Flux<SysPermission> findByRoleIds(List<Long> roleIds) {
        return permissionRepository.findByRoleIds(roleIds);
    }

    @Override
    @Transactional
    public Mono<Void> assignPermissionsToRole(Long roleId, List<Long> permissionIds) {
        return rolePermissionRepository.deleteByRoleId(roleId)
                .then(Flux.fromIterable(permissionIds)
                        .flatMap(permissionId -> {
                            SysRolePermission rolePermission = new SysRolePermission();
                            rolePermission.setRoleId(roleId);
                            rolePermission.setPermissionId(permissionId);
                            rolePermission.setCreatedAt(LocalDateTime.now());
                            return rolePermissionRepository.save(rolePermission);
                        })
                        .then());
    }

    @Override
    public Flux<SysPermission> getPermissionsByRoleId(Long roleId) {
        return permissionRepository.findByRoleId(roleId);
    }
}