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

export interface Permission {
  id: string;
  name: string;
  description: string;
  module: string;
  action: 'READ' | 'WRITE' | 'DELETE' | 'EXECUTE';
}

export interface Role {
  code: string;
  name: string;
  permissions: string[];
}

export interface UserRoleAssignment {
  userId: string;
  tenantId: string;
  roleCode: string;
  departmentId?: string;
  shopId?: string;
}

export interface DataScope {
  type: 'ALL' | 'ORG' | 'DEPT' | 'SHOP' | 'OWN';
  departmentId?: string;
  shopId?: string;
}

const PERMISSIONS: Permission[] = [
  { id: 'admin:all', name: '超级管理员', description: '拥有所有系统权限', module: 'SYSTEM', action: 'EXECUTE' },
  
  { id: 'product:read', name: '查看商品', description: '允许查看商品列表与详情', module: 'PRODUCT', action: 'READ' },
  { id: 'product:write', name: '编辑商品', description: '允许创建和修改商品信息', module: 'PRODUCT', action: 'WRITE' },
  { id: 'product:delete', name: '删除商品', description: '允许删除商品', module: 'PRODUCT', action: 'DELETE' },
  { id: 'product:publish', name: '发布商品', description: '允许执行商品刊登任务', module: 'PRODUCT', action: 'EXECUTE' },
  { id: 'product:score', name: '商品评分', description: '允许查看AI选品评分', module: 'PRODUCT', action: 'READ' },
  
  { id: 'order:read', name: '查看订单', description: '允许查看销售订单', module: 'ORDER', action: 'READ' },
  { id: 'order:write', name: '创建订单', description: '允许创建订单', module: 'ORDER', action: 'WRITE' },
  { id: 'order:cancel', name: '取消订单', description: '允许取消订单', module: 'ORDER', action: 'EXECUTE' },
  { id: 'order:refund', name: '退款处理', description: '允许处理退款', module: 'ORDER', action: 'EXECUTE' },
  
  { id: 'inventory:read', name: '查看库存', description: '允许查看库存数据', module: 'INVENTORY', action: 'READ' },
  { id: 'inventory:write', name: '编辑库存', description: '允许调整库存', module: 'INVENTORY', action: 'WRITE' },
  { id: 'inventory:sync', name: '库存同步', description: '允许执行跨平台库存同步', module: 'INVENTORY', action: 'EXECUTE' },
  { id: 'inventory:alert', name: '库存预警', description: '允许配置库存预警', module: 'INVENTORY', action: 'EXECUTE' },
  
  { id: 'finance:read', name: '查看财务', description: '允许查看财务数据', module: 'FINANCE', action: 'READ' },
  { id: 'finance:recon', name: '财务对账', description: '允许执行自动化对账', module: 'FINANCE', action: 'EXECUTE' },
  { id: 'finance:settlement', name: '结算管理', description: '允许处理结算', module: 'FINANCE', action: 'EXECUTE' },
  { id: 'finance:report', name: '财务报表', description: '允许查看财务报表', module: 'FINANCE', action: 'READ' },
  
  { id: 'ad:read', name: '查看广告', description: '允许查看广告数据', module: 'ADVERTISING', action: 'READ' },
  { id: 'ad:write', name: '编辑广告', description: '允许创建和修改广告', module: 'ADVERTISING', action: 'WRITE' },
  { id: 'ad:launch', name: '投放广告', description: '允许执行广告投放', module: 'ADVERTISING', action: 'EXECUTE' },
  { id: 'ad:optimize', name: '广告优化', description: '允许执行AI广告优化', module: 'ADVERTISING', action: 'EXECUTE' },
  
  { id: 'sourcing:read', name: '查看采购', description: '允许查看采购数据', module: 'SOURCING', action: 'READ' },
  { id: 'sourcing:write', name: '编辑采购', description: '允许创建采购单', module: 'SOURCING', action: 'WRITE' },
  { id: 'sourcing:approve', name: '采购审批', description: '允许审批采购单', module: 'SOURCING', action: 'EXECUTE' },
  
  { id: 'logistics:read', name: '查看物流', description: '允许查看物流数据', module: 'LOGISTICS', action: 'READ' },
  { id: 'logistics:write', name: '编辑物流', description: '允许配置物流', module: 'LOGISTICS', action: 'WRITE' },
  { id: 'logistics:track', name: '物流追踪', description: '允许追踪物流状态', module: 'LOGISTICS', action: 'EXECUTE' },
  
  { id: 'ai:read', name: '查看AI分析', description: '允许查看AI分析结果', module: 'AI', action: 'READ' },
  { id: 'ai:scoring', name: 'AI选品评分', description: '允许执行AI选品评分', module: 'AI', action: 'EXECUTE' },
  { id: 'ai:arbitrage', name: '套利识别', description: '允许执行套利机会识别', module: 'AI', action: 'EXECUTE' },
  { id: 'ai:pricing', name: '智能定价', description: '允许执行智能定价建议', module: 'AI', action: 'EXECUTE' },
  { id: 'ai:monitor', name: '价格监控', description: '允许配置竞争对手价格监控', module: 'AI', action: 'EXECUTE' },
  
  { id: 'collection:read', name: '查看采集', description: '允许查看采集任务', module: 'COLLECTION', action: 'READ' },
  { id: 'collection:write', name: '编辑采集', description: '允许创建采集任务', module: 'COLLECTION', action: 'WRITE' },
  { id: 'collection:execute', name: '执行采集', description: '允许执行采集任务', module: 'COLLECTION', action: 'EXECUTE' },
  
  { id: 'user:read', name: '查看用户', description: '允许查看用户列表', module: 'USER', action: 'READ' },
  { id: 'user:write', name: '编辑用户', description: '允许创建和修改用户', module: 'USER', action: 'WRITE' },
  { id: 'user:role', name: '角色管理', description: '允许分配用户角色', module: 'USER', action: 'EXECUTE' },
  
  { id: 'tenant:read', name: '查看租户', description: '允许查看租户信息', module: 'TENANT', action: 'READ' },
  { id: 'tenant:write', name: '编辑租户', description: '允许修改租户配置', module: 'TENANT', action: 'WRITE' },
  { id: 'tenant:config', name: '租户配置', description: '允许配置租户设置', module: 'TENANT', action: 'EXECUTE' },
  
  { id: 'audit:read', name: '查看审计', description: '允许查看审计日志', module: 'AUDIT', action: 'READ' },
  { id: 'audit:export', name: '导出审计', description: '允许导出审计日志', module: 'AUDIT', action: 'EXECUTE' },
];

const ROLE_PERMISSIONS: Record<string, string[]> = {
  'ADMIN': ['admin:all'],
  'MANAGER': [
    'product:read', 'product:write', 'product:publish', 'product:score',
    'order:read', 'order:write', 'order:cancel',
    'inventory:read', 'inventory:write', 'inventory:sync', 'inventory:alert',
    'finance:read', 'finance:report',
    'ad:read', 'ad:write', 'ad:launch', 'ad:optimize',
    'sourcing:read', 'sourcing:write',
    'logistics:read', 'logistics:track',
    'ai:read', 'ai:scoring', 'ai:arbitrage', 'ai:pricing', 'ai:monitor',
    'collection:read', 'collection:write', 'collection:execute',
    'user:read',
    'audit:read'
  ],
  'OPERATOR': [
    'product:read', 'product:write', 'product:publish',
    'order:read', 'order:write',
    'inventory:read', 'inventory:sync',
    'ad:read', 'ad:write',
    'sourcing:read',
    'logistics:read', 'logistics:track',
    'ai:read', 'ai:scoring',
    'collection:read', 'collection:execute'
  ],
  'FINANCE': [
    'order:read', 'order:refund',
    'finance:read', 'finance:recon', 'finance:settlement', 'finance:report',
    'audit:read', 'audit:export'
  ],
  'SOURCING': [
    'product:read', 'product:score',
    'inventory:read',
    'sourcing:read', 'sourcing:write', 'sourcing:approve',
    'ai:read', 'ai:scoring', 'ai:arbitrage',
    'collection:read', 'collection:execute'
  ],
  'LOGISTICS': [
    'order:read',
    'inventory:read', 'inventory:sync',
    'logistics:read', 'logistics:write', 'logistics:track'
  ],
  'ANALYST': [
    'product:read', 'product:score',
    'order:read',
    'inventory:read',
    'finance:read', 'finance:report',
    'ad:read',
    'ai:read', 'ai:scoring', 'ai:arbitrage', 'ai:pricing', 'ai:monitor',
    'audit:read'
  ]
};

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(): Promise<void> {
    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.string('module', 64).notNullable();
        table.enum('action', ['READ', 'WRITE', 'DELETE', 'EXECUTE']).notNullable();
        table.timestamps(true, true);
        table.index('module');
      });

      for (const perm of PERMISSIONS) {
        await db(this.PERMISSIONS_TABLE).insert({
          id: perm.id,
          name: perm.name,
          description: perm.description,
          module: perm.module,
          action: perm.action
        });
      }
      logger.info(`✅ Inserted ${PERMISSIONS.length} permissions`);
    }

    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();
        table.timestamps(true, true);
      });

      const roleNames: Record<string, string> = {
        'ADMIN': '管理员',
        'MANAGER': '运营主管',
        'OPERATOR': '运营专员',
        'FINANCE': '财务主管',
        'SOURCING': '采购专家',
        'LOGISTICS': '物流专家',
        'ANALYST': '数据分析师'
      };

      for (const [code, perms] of Object.entries(ROLE_PERMISSIONS)) {
        await db(this.ROLES_TABLE).insert({
          code,
          name: roleNames[code] || code,
          permissions: JSON.stringify(perms)
        });
      }
      logger.info(`✅ Inserted ${Object.keys(ROLE_PERMISSIONS).length} roles`);
    }

    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.string('department_id', 64);
        table.string('shop_id', 64);
        table.unique(['user_id', 'tenant_id', 'role_code']);
        table.index(['user_id', 'tenant_id']);
        table.index(['tenant_id', 'role_code']);
        table.timestamps(true, true);
      });
    }
  }

  static async authorize(userId: string, tenantId: string, requiredPermission: string): Promise<boolean> {
    try {
      const userRoles = await db(this.USER_ROLES_TABLE)
        .where({ user_id: userId, tenant_id: tenantId })
        .select('role_code');
      
      if (userRoles.length === 0) return false;

      const roleCodes = userRoles.map(ur => ur.role_code);
      const roles = await db(this.ROLES_TABLE).whereIn('code', roleCodes);

      const allPermissions = new Set<string>();
      roles.forEach(role => {
        const perms = JSON.parse(role.permissions || '[]');
        perms.forEach((p: string) => allPermissions.add(p));
      });

      if (allPermissions.has('admin:all')) return true;
      return allPermissions.has(requiredPermission);
    } catch (err: unknown) {
      const errorMessage = err instanceof Error ? err.message : 'Unknown error';
      logger.error(`[RBAC] Authorization failed for user ${userId}: ${errorMessage}`);
      return false;
    }
  }

  static async getDataScope(userId: string, tenantId: string): Promise<DataScope> {
    const userRoles = await db(this.USER_ROLES_TABLE)
      .where({ user_id: userId, tenant_id: tenantId })
      .select('role_code', 'department_id', 'shop_id');
    
    if (userRoles.length === 0) {
      return { type: 'OWN' };
    }

    const roleCodes = userRoles.map(ur => ur.role_code);
    
    if (roleCodes.includes('ADMIN')) {
      return { type: 'ALL' };
    }
    
    if (roleCodes.includes('MANAGER')) {
      const deptId = userRoles.find(ur => ur.department_id)?.department_id;
      return { type: 'DEPT', departmentId: deptId };
    }

    const shopId = userRoles.find(ur => ur.shop_id)?.shop_id;
    if (shopId) {
      return { type: 'SHOP', shopId };
    }

    return { type: 'OWN' };
  }

  static async assignRole(assignment: UserRoleAssignment): Promise<boolean> {
    try {
      await db(this.USER_ROLES_TABLE).insert({
        user_id: assignment.userId,
        tenant_id: assignment.tenantId,
        role_code: assignment.roleCode,
        department_id: assignment.departmentId,
        shop_id: assignment.shopId
      });
      return true;
    } catch (err: unknown) {
      const errorMessage = err instanceof Error ? err.message : 'Unknown error';
      logger.error(`[RBAC] Failed to assign role: ${errorMessage}`);
      return false;
    }
  }

  static async removeRole(userId: string, tenantId: string, roleCode: string): Promise<boolean> {
    try {
      await db(this.USER_ROLES_TABLE)
        .where({ user_id: userId, tenant_id: tenantId, role_code: roleCode })
        .delete();
      return true;
    } catch (err: unknown) {
      const errorMessage = err instanceof Error ? err.message : 'Unknown error';
      logger.error(`[RBAC] Failed to remove role: ${errorMessage}`);
      return false;
    }
  }

  static async getUserRoles(userId: string, tenantId: string): Promise<string[]> {
    const userRoles = await db(this.USER_ROLES_TABLE)
      .where({ user_id: userId, tenant_id: tenantId })
      .select('role_code');
    
    return userRoles.map(ur => ur.role_code);
  }

  static async getUserPermissions(userId: string, tenantId: string): Promise<string[]> {
    const roleCodes = await this.getUserRoles(userId, tenantId);
    if (roleCodes.length === 0) return [];

    const roles = await db(this.ROLES_TABLE).whereIn('code', roleCodes);
    
    const allPermissions = new Set<string>();
    roles.forEach(role => {
      const perms = JSON.parse(role.permissions || '[]');
      perms.forEach((p: string) => allPermissions.add(p));
    });

    return Array.from(allPermissions);
  }

  static async hasAnyPermission(userId: string, tenantId: string, permissions: string[]): Promise<boolean> {
    const userPermissions = await this.getUserPermissions(userId, tenantId);
    if (userPermissions.includes('admin:all')) return true;
    return permissions.some(p => userPermissions.includes(p));
  }

  static async hasAllPermissions(userId: string, tenantId: string, permissions: string[]): Promise<boolean> {
    const userPermissions = await this.getUserPermissions(userId, tenantId);
    if (userPermissions.includes('admin:all')) return true;
    return permissions.every(p => userPermissions.includes(p));
  }

  static getPermissionDefinitions(): Permission[] {
    return PERMISSIONS;
  }

  static getRoleDefinitions(): Record<string, string[]> {
    return ROLE_PERMISSIONS;
  }
}
