import { randomInt } from "./random";
import type {
  ChallengeId,
  ChallengeMetric,
  ChallengeMetrics,
  ChallengeObjective,
  ChallengeResult,
  RandomState,
} from "./types";

export interface ChallengeDefinition {
  readonly id: ChallengeId;
  readonly name: string;
  readonly metric: ChallengeMetric;
  readonly targets: readonly number[];
  readonly baseCurrency: number;
}

export const CHALLENGE_REGISTRY: Record<ChallengeId, ChallengeDefinition> = {
  blockbreaker: {
    id: "blockbreaker",
    name: "Brickbreaker Trial",
    metric: "bricksBroken",
    targets: [30, 45, 60],
    baseCurrency: 24,
  },
  hockey: {
    id: "hockey",
    name: "Hockey Shutout",
    metric: "bossKills",
    targets: [1, 2, 3],
    baseCurrency: 28,
  },
  "aether-assault": {
    id: "aether-assault",
    name: "Aether Assault",
    metric: "kills",
    targets: [20, 35, 50],
    baseCurrency: 24,
  },
};

export const CHALLENGE_ORDER = Object.keys(CHALLENGE_REGISTRY) as ChallengeId[];

export function emptyChallengeMetrics(): ChallengeMetrics {
  return { bricksBroken: 0, bossKills: 0, kills: 0 };
}

export function emptyChallengeCounts(): Record<ChallengeId, number> {
  return { blockbreaker: 0, hockey: 0, "aether-assault": 0 };
}

export function challengeObjective(challengeId: ChallengeId, priorOccurrences: number): ChallengeObjective {
  const definition = CHALLENGE_REGISTRY[challengeId];
  const repeatIndex = Math.max(0, Math.floor(priorOccurrences));
  const tier = Math.min(repeatIndex, definition.targets.length - 1);
  return {
    challengeId,
    name: definition.name,
    metric: definition.metric,
    target: definition.targets[tier],
    repeatIndex,
    rewardCurrency: definition.baseCurrency + tier * 8,
    chestQualityBonus: tier >= 2 ? 2 : 1,
  };
}

export function selectChallenge(
  source: RandomState,
  counts: Readonly<Record<ChallengeId, number>>,
): {
  objective: ChallengeObjective;
  counts: Record<ChallengeId, number>;
  random: RandomState;
} {
  const sampled = randomInt(source, CHALLENGE_ORDER.length);
  const challengeId = CHALLENGE_ORDER[sampled.value];
  const priorOccurrences = counts[challengeId] ?? 0;
  return {
    objective: challengeObjective(challengeId, priorOccurrences),
    counts: { ...counts, [challengeId]: priorOccurrences + 1 },
    random: sampled.random,
  };
}

export function mergeChallengeMetrics(
  current: ChallengeMetrics,
  update: Partial<ChallengeMetrics>,
): ChallengeMetrics {
  return {
    bricksBroken: Math.max(0, Math.floor(update.bricksBroken ?? current.bricksBroken)),
    bossKills: Math.max(0, Math.floor(update.bossKills ?? current.bossKills)),
    kills: Math.max(0, Math.floor(update.kills ?? current.kills)),
  };
}

export function evaluateChallenge(objective: ChallengeObjective, metrics: ChallengeMetrics): ChallengeResult {
  return { objective, metrics, succeeded: metrics[objective.metric] >= objective.target };
}

