import db from '../../config/database';
import { logger } from '../../utils/logger';

export interface Permission {
  id: string;
  name: string;
  description: string;
}

export interface Role {
  code: string;
  name: string;
  permissions: string[]; // 权限点列表
}

/**
 * [BIZ_RBAC_01] 多租户细粒度权限校验引擎 (Granular RBAC Engine)
 * @description 核心逻辑：基于角色与权限点的 RBAC 模型，支持多租户隔离。
 */
export class RBACEngine {
  private static readonly ROLES_TABLE = 'cf_roles';
  private static readonly PERMISSIONS_TABLE = 'cf_permissions';
  private static readonly USER_ROLES_TABLE = 'cf_user_roles';

  /**
   * 初始化数据库表
   */
  static async initTable() {
    const hasPermissionsTable = await db.schema.hasTable(this.PERMISSIONS_TABLE);
    if (!hasPermissionsTable) {
      logger.info(`📦 Creating ${this.PERMISSIONS_TABLE} table...`);
      await db.schema.createTable(this.PERMISSIONS_TABLE, (table) => {
        table.string('id', 64).primary();
        table.string('name', 128).notNullable();
        table.string('description', 255);
        table.timestamps(true, true);
      });

      // 预设权限点
      await db(this.PERMISSIONS_TABLE).insert([
        { id: 'product:read', name: '查看商品', description: '允许查看商品列表与详情' },
        { id: 'product:edit', name: '编辑商品', description: '允许修改商品信息' },
        { id: 'product:publish', name: '发布商品', description: '允许执行商品刊登任务' },
        { id: 'order:read', name: '查看订单', description: '允许查看销售订单' },
        { id: 'finance:recon', name: '财务对账', description: '允许执行自动化对账' },
        { id: 'admin:all', name: '超级管理员', description: '拥有所有系统权限' }
      ]);
    }

    const hasRolesTable = await db.schema.hasTable(this.ROLES_TABLE);
    if (!hasRolesTable) {
      logger.info(`📦 Creating ${this.ROLES_TABLE} table...`);
      await db.schema.createTable(this.ROLES_TABLE, (table) => {
        table.string('code', 64).primary();
        table.string('name', 128).notNullable();
        table.json('permissions').notNullable(); // 存储权限点 ID 数组
        table.timestamps(true, true);
      });

      // 预设角色
      await db(this.ROLES_TABLE).insert([
        { code: 'ADMIN', name: '管理员', permissions: JSON.stringify(['admin:all']) },
        { code: 'OPERATOR', name: '运营专员', permissions: JSON.stringify(['product:read', 'product:edit', 'product:publish', 'order:read']) },
        { code: 'FINANCE', name: '财务主管', permissions: JSON.stringify(['order:read', 'finance:recon']) }
      ]);
    }

    const hasUserRolesTable = await db.schema.hasTable(this.USER_ROLES_TABLE);
    if (!hasUserRolesTable) {
      logger.info(`📦 Creating ${this.USER_ROLES_TABLE} table...`);
      await db.schema.createTable(this.USER_ROLES_TABLE, (table) => {
        table.increments('id').primary();
        table.string('user_id', 64).notNullable();
        table.string('tenant_id', 64).notNullable();
        table.string('role_code', 64).notNullable();
        table.unique(['user_id', 'tenant_id', 'role_code']);
        table.index(['user_id', 'tenant_id']);
        table.timestamps(true, true);
      });
    }
  }

  /**
   * 校验用户在指定租户下是否拥有权限
   */
  static async authorize(userId: string, tenantId: string, requiredPermission: string): Promise<boolean> {
    try {
      // 1. 获取用户在当前租户下的所有角色
      const userRoles = await db(this.USER_ROLES_TABLE)
        .where({ user_id: userId, tenant_id: tenantId })
        .select('role_code');
      
      if (userRoles.length === 0) return false;

      // 2. 获取角色的权限详情
      const roleCodes = userRoles.map(ur => ur.role_code);
      const roles = await db(this.ROLES_TABLE).whereIn('code', roleCodes);

      // 3. 展开所有权限点并去重
      const allPermissions = new Set<string>();
      roles.forEach(role => {
        const perms = JSON.parse(role.permissions || '[]');
        perms.forEach((p: string) => allPermissions.add(p));
      });

      // 4. 校验逻辑：超级管理员权限 (admin:all) 或 包含目标权限点
      if (allPermissions.has('admin:all')) return true;
      return allPermissions.has(requiredPermission);
    } catch (err: any) {
      logger.error(`[RBAC] Authorization failed for user ${userId}: ${err.message}`);
      return false;
    }
  }

  /**
   * 获取用户在租户下的数据过滤范围 (Data Scope)
   * @description 以后可扩展为基于组织架构的层级过滤
   */
  static async getDataScope(userId: string, tenantId: string): Promise<{ type: 'ALL' | 'OWN' | 'ORG', orgIds?: string[] }> {
    const userRoles = await db(this.USER_ROLES_TABLE)
      .where({ user_id: userId, tenant_id: tenantId })
      .select('role_code');
    
    const roleCodes = userRoles.map(ur => ur.role_code);
    if (roleCodes.includes('ADMIN')) return { type: 'ALL' };
    
    // 默认仅能看到自己及下属数据（简化逻辑）
    return { type: 'OWN' };
  }
}
