import { DataSource } from 'typeorm';
import { Role } from '../entities/role.entity';
import { UserEntity } from '../entities/user.entity';
import { GenericCrudService } from '@d8d/shared-crud';

export class RoleService extends GenericCrudService<Role> {
  private userRepository = this.dataSource.getRepository(UserEntity);

  constructor(dataSource: DataSource) {
    super(dataSource, Role);
  }

  // 可以添加角色特有的业务逻辑方法
  async getRoleByName(name: string, tenantId?: number): Promise<Role | null> {
    const where: any = { name };
    if (tenantId !== undefined) {
      where.tenantId = tenantId;
    }
    return this.repository.findOneBy(where);
  }

  async hasPermission(roleId: number, permission: string): Promise<boolean> {
    const role = await this.getById(roleId);
    if (!role) return false;
    return role.permissions.includes(permission);
  }

  /**
   * 检查用户是否拥有指定权限
   * @param userId 用户ID
   * @param permission 权限字符串
   * @param tenantId 租户ID（可选，如果用户实体包含租户信息）
   */
  async checkUserPermission(userId: number, permission: string, tenantId?: number): Promise<boolean> {
    const user = await this.userRepository.findOne({
      where: { id: userId },
      relations: ['roles'],
    });
    if (!user || !user.roles || user.roles.length === 0) {
      return false;
    }

    // 如果指定了租户ID，过滤角色
    const roles = tenantId !== undefined
      ? user.roles.filter(role => role.tenantId === tenantId)
      : user.roles;

    return roles.some(role => role.permissions.includes(permission));
  }

  /**
   * 获取用户的所有权限列表（去重）
   * @param userId 用户ID
   * @param tenantId 租户ID（可选）
   */
  async getUserPermissions(userId: number, tenantId?: number): Promise<string[]> {
    const user = await this.userRepository.findOne({
      where: { id: userId },
      relations: ['roles'],
    });
    if (!user || !user.roles || user.roles.length === 0) {
      return [];
    }

    // 如果指定了租户ID，过滤角色
    const roles = tenantId !== undefined
      ? user.roles.filter(role => role.tenantId === tenantId)
      : user.roles;

    // 收集所有权限并去重
    const permissionSet = new Set<string>();
    roles.forEach(role => {
      role.permissions.forEach(permission => {
        if (permission.trim()) {
          permissionSet.add(permission.trim());
        }
      });
    });

    return Array.from(permissionSet);
  }

  /**
   * 为用户分配角色
   * @param userId 用户ID
   * @param roleId 角色ID
   * @param tenantId 租户ID（可选，用于验证角色属于同一租户）
   */
  async assignRoleToUser(userId: number, roleId: number, tenantId?: number): Promise<void> {
    const user = await this.userRepository.findOne({
      where: { id: userId },
      relations: ['roles'],
    });
    if (!user) {
      throw new Error(`用户不存在: ${userId}`);
    }

    const role = await this.repository.findOne({
      where: { id: roleId },
    });
    if (!role) {
      throw new Error(`角色不存在: ${roleId}`);
    }

    // 租户验证（如果提供了租户ID）
    if (tenantId !== undefined && role.tenantId !== tenantId) {
      throw new Error(`角色不属于租户 ${tenantId}`);
    }

    // 检查用户是否已经拥有该角色
    const hasRole = user.roles.some(r => r.id === roleId);
    if (hasRole) {
      return; // 已拥有，无需操作
    }

    // 添加角色
    user.roles.push(role);
    await this.userRepository.save(user);
  }

  /**
   * 从用户移除角色
   * @param userId 用户ID
   * @param roleId 角色ID
   */
  async removeRoleFromUser(userId: number, roleId: number): Promise<void> {
    const user = await this.userRepository.findOne({
      where: { id: userId },
      relations: ['roles'],
    });
    if (!user) {
      throw new Error(`用户不存在: ${userId}`);
    }

    // 过滤掉要移除的角色
    const initialLength = user.roles.length;
    user.roles = user.roles.filter(role => role.id !== roleId);

    if (user.roles.length < initialLength) {
      await this.userRepository.save(user);
    }
  }

  /**
   * 获取用户的角色列表
   * @param userId 用户ID
   * @param tenantId 租户ID（可选）
   */
  async getUserRoles(userId: number, tenantId?: number): Promise<Role[]> {
    const user = await this.userRepository.findOne({
      where: { id: userId },
      relations: ['roles'],
    });
    if (!user || !user.roles) {
      return [];
    }

    if (tenantId !== undefined) {
      return user.roles.filter(role => role.tenantId === tenantId);
    }

    return user.roles;
  }
}