import { Aggregation } from './evals/aggregations.js';

type Score<TMetadata extends Record<string, any> = Record<string, any>> = {
    score: number | boolean | null;
    metadata?: TMetadata;
};
type ScoreWithName<TMetadata extends Record<string, any> = Record<string, any>> = Score<TMetadata> & {
    name: string;
    /** Per-trial scores when running multiple trials */
    trials?: number[];
    /** Aggregation type used (e.g., 'mean', 'pass@k') */
    aggregation?: string;
    /** Threshold for pass-based aggregations */
    threshold?: number;
};
/**
 * Configuration options for a scorer.
 */
type ScorerOptions = {
    /**
     * Aggregation function for combining scores across multiple trials.
     * Defaults to Mean() if not specified.
     */
    aggregation?: Aggregation;
};
type ScorerLike<TInput = any, TExpected = any, TOutput = any, TExtra extends Record<string, any> = {}, TMetadata extends Record<string, any> = Record<string, any>, TReturn extends Score<TMetadata> | Promise<Score<TMetadata>> = Score<TMetadata> | Promise<Score<TMetadata>>> = (args: {
    input?: TInput;
    expected?: TExpected;
    output: TOutput;
    /** Current trial index (0-based) when running multiple trials */
    trialIndex?: number;
} & TExtra) => TReturn;
type Scorer<TInput = any, TExpected = any, TOutput = any, TExtra extends Record<string, any> = {}, TMetadata extends Record<string, any> = Record<string, any>, TReturn extends Score<TMetadata> | Promise<Score<TMetadata>> = Score<TMetadata> | Promise<Score<TMetadata>>> = ScorerLike<TInput, TExpected, TOutput, TExtra, TMetadata, TReturn> & {
    readonly name: string;
    readonly aggregation?: Aggregation;
};

type ValidChars =
  | 'a'
  | 'b'
  | 'c'
  | 'd'
  | 'e'
  | 'f'
  | 'g'
  | 'h'
  | 'i'
  | 'j'
  | 'k'
  | 'l'
  | 'm'
  | 'n'
  | 'o'
  | 'p'
  | 'q'
  | 'r'
  | 's'
  | 't'
  | 'u'
  | 'v'
  | 'w'
  | 'x'
  | 'y'
  | 'z'
  | 'A'
  | 'B'
  | 'C'
  | 'D'
  | 'E'
  | 'F'
  | 'G'
  | 'H'
  | 'I'
  | 'J'
  | 'K'
  | 'L'
  | 'M'
  | 'N'
  | 'O'
  | 'P'
  | 'Q'
  | 'R'
  | 'S'
  | 'T'
  | 'U'
  | 'V'
  | 'W'
  | 'X'
  | 'Y'
  | 'Z'
  | '0'
  | '1'
  | '2'
  | '3'
  | '4'
  | '5'
  | '6'
  | '7'
  | '8'
  | '9'
  | '-'
  | '_';

type ValidateName<T extends string, Original extends string = T> =
  // For widened strings, don't attempt validation – let them flow through unchanged
  string extends T // string is not wider than T, ie T is string
    ? T
    : T extends ''
      ? Original extends ''
        ? '❌ Name cannot be empty'
        : Original
      : T extends `${infer First}${infer Rest}`
        ? First extends ValidChars
          ? ValidateName<Rest, Original>
          : `❌ Invalid character in "${Original}". Only A-Z, a-z, 0-9, -, _ allowed`
        : never;

export type { ScoreWithName as S, ValidateName as V, ScorerLike as a, Score as b, ScorerOptions as c, Scorer as d };
