import {
  Injectable,
  CanActivate,
  ExecutionContext,
  ForbiddenException,
  Logger,
} from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { CAPABILITY_KEY } from '../decorators/require-capability.decorator';
import { CapabilityService } from '@/application/services/capability.service';
import { Capability } from '@/domain/value-objects/capability.vo';

const CAPABILITY_LABELS: Record<string, string> = {
  LOGIN: '登录',
  TRADING: '交易',
  C2C: 'C2C交易',
  TRANSFER_IN: '划入',
  TRANSFER_OUT: '划出',
  P2P_SEND: 'P2P转出',
  P2P_RECEIVE: 'P2P收款',
  MINING_CLAIM: '挖矿领取',
  KYC: '实名认证',
  PROFILE_EDIT: '编辑资料',
  VIEW_ASSET: '查看资产',
  VIEW_TEAM: '查看团队',
  VIEW_RECORDS: '查看记录',
};

/**
 * CapabilityGuard - auth-service 内部版本，直接使用 CapabilityService
 * 必须在 JwtAuthGuard 之后使用，依赖 request.user.accountSequence
 */
@Injectable()
export class CapabilityGuard implements CanActivate {
  private readonly logger = new Logger(CapabilityGuard.name);

  constructor(
    private readonly reflector: Reflector,
    private readonly capabilityService: CapabilityService,
  ) {}

  async canActivate(context: ExecutionContext): Promise<boolean> {
    const requiredCapability = this.reflector.getAllAndOverride<string>(
      CAPABILITY_KEY,
      [context.getHandler(), context.getClass()],
    );

    // 无能力要求 → 放行
    if (!requiredCapability) return true;

    const request = context.switchToHttp().getRequest();
    const accountSequence = request.user?.accountSequence;

    // 未认证（公开端点或认证前） → 放行
    if (!accountSequence) return true;

    try {
      const isEnabled = await this.capabilityService.isCapabilityEnabled(
        accountSequence,
        requiredCapability as Capability,
      );

      if (!isEnabled) {
        const label = CAPABILITY_LABELS[requiredCapability] || requiredCapability;
        throw new ForbiddenException({
          code: 'CAPABILITY_DISABLED',
          capability: requiredCapability,
          message: `您的${label}功能已被限制`,
        });
      }

      return true;
    } catch (error) {
      if (error instanceof ForbiddenException) throw error;
      // 服务错误 → fail-open
      this.logger.warn(`能力检查失败 (fail-open): ${accountSequence}`, error?.message);
      return true;
    }
  }
}
