import {
  CanActivate,
  ExecutionContext,
  ForbiddenException,
  Injectable,
} from '@nestjs/common';

//* AdminJwtAuthGuard 가 request 에 실어 주는 신원. 컨트롤러가 `req: any` 를 쓰지 않도록 여기서 낸다.
export interface AdminIdentity {
  role?: string;
  admId?: number;
  adminViewToken?: boolean;
}

export interface AdminRequest {
  admin?: AdminIdentity;
}

/**
 * 알림 설정 권한 — env 허용목록(ALERT_ADMIN_IDS, CSV)에 등재된 최상위 관리자만.
 *
 * car-view-admin.guard.ts 에서 승계하는 것은 `env CSV → Set → has()` 와
 * 빈 목록 fail-closed **두 가지뿐**이다. 그 파일 :27 의 `corp` 우회 분기는
 * 허용목록을 통과하지 않고 승인하므로 여기 복제하면 PRD M12 를 정면 위반한다(D5).
 *
 * `process.env` 를 직접 읽는 이유: 이 판정은 가드(DI 있음)와 레거시 컨트롤러 분기(DI 없는 순수 호출)
 * 두 곳에서 같은 답을 내야 한다. ConfigService 로 옮기면 순수 함수가 아니게 되어 호출부마다
 * 주입을 끌고 다녀야 하고, 허용목록의 출처가 둘로 갈라진다.
 */
export function canManageAlert(admin: AdminIdentity | undefined): boolean {
  if (!admin?.role) return false;

  //* admin-view 경유 토큰은 알림 설정 권한을 담지 않는다 — 그 토큰으로는 통과시키지 않는다.
  const tokenOk = admin.adminViewToken !== true;

  const allowed = new Set(
    (process.env.ALERT_ADMIN_IDS ?? '')
      .split(',')
      .map((id) => id.trim())
      .filter(Boolean),
  );

  //* corp/sales 예외 분기 없음. role 이 정확히 'admin' 이고 허용목록에 있을 때만 true.
  return admin.role === 'admin' && allowed.has(String(admin.admId)) && tokenOk;
}

/** 알림 설정 API 접근 제한. 빈 허용목록은 admin 에 대해 fail-closed. */
@Injectable()
export class AlertAdminGuard implements CanActivate {
  canActivate(context: ExecutionContext): boolean {
    const { admin } = context.switchToHttp().getRequest<AdminRequest>();
    if (canManageAlert(admin)) return true;
    throw new ForbiddenException('알림 설정 권한이 없습니다');
  }
}
