// Local type aliases matching the contracts in @repo/core-shared/rate-limit.
// Kept inline to avoid a build-graph cycle between core-testing and core-shared
// (mirrors the recording-job-queue pattern).

type RateLimitDecision = {
  allowed: boolean;
  remaining: number;
  resetAt: Date;
};

interface IRateLimit {
  consume(
    budgetName: string,
    key: string,
    weight?: number,
  ): Promise<RateLimitDecision>;
  reset(budgetName: string, key: string): Promise<void>;
}

export type RecordedConsumeCall = {
  budgetName: string;
  key: string;
  weight: number | undefined;
};

export type RecordedResetCall = {
  budgetName: string;
  key: string;
};

const EPOCH = new Date(0);

export class RecordingRateLimit implements IRateLimit {
  readonly consumeCalls: RecordedConsumeCall[] = [];
  readonly resetCalls: RecordedResetCall[] = [];

  private _decision: RateLimitDecision = {
    allowed: true,
    remaining: Infinity,
    resetAt: EPOCH,
  };

  withDecision(decision: RateLimitDecision): this {
    this._decision = decision;
    return this;
  }

  async consume(
    budgetName: string,
    key: string,
    weight?: number,
  ): Promise<RateLimitDecision> {
    this.consumeCalls.push({ budgetName, key, weight });
    return this._decision;
  }

  async reset(budgetName: string, key: string): Promise<void> {
    this.resetCalls.push({ budgetName, key });
  }
}
