import { Type } from 'class-transformer';
import { IsEnum, IsISO8601, IsOptional, IsString, MaxLength } from 'class-validator';

/**
 * Query parameters for `GET /api/admin/audit/stats`. Mirrors the
 * filter shape of {@link AdminAuditQueryDto} **minus pagination**:
 * the stats endpoint always aggregates the whole filtered set, so
 * `limit` / `offset` carry no meaning.
 *
 * Per the chantier brief, the endpoint respects filters strictly —
 * an unfiltered call aggregates across the full audit retention
 * (365 days by default per ADR-0013). The 5-minute Redis cache
 * absorbs the cost of a heavy unfiltered query if the same shape
 * lands twice in quick succession.
 */

/** Subset of `AuditAudience` accepted by the filter — matches the list endpoint. */
const AUDIT_AUDIENCES = ['workforce', 'customer'] as const;
type AuditAudienceFilter = (typeof AUDIT_AUDIENCES)[number];

/** Subset of `AuditOutcome` accepted by the filter. */
const AUDIT_OUTCOMES = ['success', 'failure', 'denied'] as const;
type AuditOutcomeFilter = (typeof AUDIT_OUTCOMES)[number];

export class AdminAuditStatsQueryDto {
  @IsOptional()
  @IsString()
  @MaxLength(128)
  eventType?: string;

  @IsOptional()
  @IsString()
  @MaxLength(128)
  actorIdHash?: string;

  @IsOptional()
  @IsEnum(AUDIT_AUDIENCES)
  audience?: AuditAudienceFilter;

  @IsOptional()
  @IsEnum(AUDIT_OUTCOMES)
  outcome?: AuditOutcomeFilter;

  @IsOptional()
  @IsString()
  @MaxLength(128)
  subjectPrefix?: string;

  @IsOptional()
  @IsISO8601()
  createdAtFrom?: string;

  @IsOptional()
  @IsISO8601()
  @Type(() => String)
  createdAtTo?: string;
}
