// economy.ts — Core clicker logic (lazy calculation pattern)
// Jamais de timer actif : tout est calculé au read depuis lastTick

export interface Generator {
  id: string;
  name: string;
  baseCost: number;
  baseProduction: number; // ressource/s
  owned: number;
}

export type EffectType = "click_multiplier" | "production_multiplier" | "start_bonus" | "unlock_generator" | "achievement_scaling";

export interface EvolutionNode {
  id: string;
  name: string;
  cost: number;        // en ADN Ancestral
  effect: EffectType;
  value: number;
  unlocked: boolean;
  requires: string | null; // id du nœud prérequis (null = racine)
}

export interface GameState {
  resources: number;
  clickMultiplier: number;
  generators: Generator[];
  lastTick: number; // timestamp ms — lazy calc reference
  prestigeCount: number;
  prestigeMultiplier: number; // legacy — conservé pour compat, remplacé par arbre
  ancestralDna: number;
  evolutionTree: EvolutionNode[];
  lifetimeTadpoles: number; // total cumulé de la run (pour calcul ADN)
}

// --- Arbre d'Évolution ---

export const DEFAULT_EVOLUTION_TREE: EvolutionNode[] = [
  { id: "ponte_amelioree",    name: "Ponte Améliorée",    cost: 1,  effect: "click_multiplier",       value: 2,    unlocked: false, requires: null },
  { id: "instinct_gregaire",  name: "Instinct Grégaire",  cost: 3,  effect: "production_multiplier",  value: 1.5,  unlocked: false, requires: "ponte_amelioree" },
  { id: "memoire_genetique",  name: "Mémoire Génétique",  cost: 10, effect: "start_bonus",            value: 100,  unlocked: false, requires: "instinct_gregaire" },
  { id: "mutation_alpha",     name: "Mutation Alpha",      cost: 25, effect: "unlock_generator",       value: 0,    unlocked: false, requires: "memoire_genetique" },
  { id: "symbiose",           name: "Symbiose",           cost: 50, effect: "achievement_scaling",    value: 0.01, unlocked: false, requires: "mutation_alpha" },
];

// Calcule l'ADN gagné lors d'un prestige : floor(150 × sqrt(lifetime / 1e9))
export function computePrestigeDna(lifetimeTadpoles: number): number {
  return Math.floor(150 * Math.sqrt(lifetimeTadpoles / 1e9));
}

// Vérifie si un nœud peut être acheté
export function canBuyEvolutionNode(state: GameState, nodeId: string): boolean {
  const node = state.evolutionTree.find((n) => n.id === nodeId);
  if (!node || node.unlocked) return false;
  if (state.ancestralDna < node.cost) return false;
  if (node.requires) {
    const prereq = state.evolutionTree.find((n) => n.id === node.requires);
    if (!prereq || !prereq.unlocked) return false;
  }
  return true;
}

// Achète un nœud d'évolution (retourne null si impossible)
export function buyEvolutionNode(state: GameState, nodeId: string): GameState | null {
  if (!canBuyEvolutionNode(state, nodeId)) return null;

  const node = state.evolutionTree.find((n) => n.id === nodeId)!;
  return {
    ...state,
    ancestralDna: state.ancestralDna - node.cost,
    evolutionTree: state.evolutionTree.map((n) =>
      n.id === nodeId ? { ...n, unlocked: true } : n
    ),
  };
}

// Calcule le multiplicateur click total depuis l'arbre
export function getClickMultiplierFromTree(tree: EvolutionNode[]): number {
  return tree
    .filter((n) => n.unlocked && n.effect === "click_multiplier")
    .reduce((mult, n) => mult * n.value, 1);
}

// Calcule le multiplicateur production total depuis l'arbre
export function getProductionMultiplierFromTree(tree: EvolutionNode[]): number {
  return tree
    .filter((n) => n.unlocked && n.effect === "production_multiplier")
    .reduce((mult, n) => mult * n.value, 1);
}

// Bonus de départ (têtards offerts au début de chaque run)
export function getStartBonusFromTree(tree: EvolutionNode[]): number {
  return tree
    .filter((n) => n.unlocked && n.effect === "start_bonus")
    .reduce((sum, n) => sum + n.value, 0);
}

// --- Core economy (mis à jour pour intégrer l'arbre) ---

// Coût d'achat du N-ième générateur : baseCost × 1.15^owned
export function generatorCost(gen: Generator): number {
  return Math.floor(gen.baseCost * Math.pow(1.15, gen.owned));
}

// Production totale par seconde de tous les générateurs
export function totalProductionPerSecond(state: GameState): number {
  const base = state.generators.reduce(
    (sum, gen) => sum + gen.baseProduction * gen.owned,
    0
  );
  const treeMultiplier = getProductionMultiplierFromTree(state.evolutionTree);
  return base * state.prestigeMultiplier * treeMultiplier;
}

// Lazy calculation : ressources accumulées depuis lastTick
export function computeIdleGains(state: GameState, now: number): number {
  const elapsedSeconds = (now - state.lastTick) / 1000;
  return totalProductionPerSecond(state) * elapsedSeconds;
}

// Applique les gains idle et met à jour lastTick
export function applyIdleGains(state: GameState, now: number): GameState {
  const gains = computeIdleGains(state, now);
  return {
    ...state,
    resources: state.resources + gains,
    lifetimeTadpoles: state.lifetimeTadpoles + gains,
    lastTick: now,
  };
}

// Clic manuel
export function applyClick(state: GameState): GameState {
  const treeClickMult = getClickMultiplierFromTree(state.evolutionTree);
  const gain = state.clickMultiplier * state.prestigeMultiplier * treeClickMult;
  return {
    ...state,
    resources: state.resources + gain,
    lifetimeTadpoles: state.lifetimeTadpoles + gain,
  };
}

// Achat d'un générateur (retourne null si fonds insuffisants)
export function buyGenerator(state: GameState, genId: string): GameState | null {
  const genIndex = state.generators.findIndex((g) => g.id === genId);
  if (genIndex === -1) return null;

  const gen = state.generators[genIndex];
  const cost = generatorCost(gen);
  if (state.resources < cost) return null;

  const updatedGenerators = [...state.generators];
  updatedGenerators[genIndex] = { ...gen, owned: gen.owned + 1 };

  return {
    ...state,
    resources: state.resources - cost,
    generators: updatedGenerators,
  };
}

// Prestige : reset run, gain ADN, arbre persiste
export function canPrestige(state: GameState): boolean {
  return state.resources >= 1_000_000;
}

export function applyPrestige(state: GameState): GameState {
  const newPrestigeCount = state.prestigeCount + 1;
  const dnaGained = computePrestigeDna(state.lifetimeTadpoles);
  const startBonus = getStartBonusFromTree(state.evolutionTree);

  return {
    ...state,
    resources: startBonus,
    generators: state.generators.map((g) => ({ ...g, owned: 0 })),
    prestigeCount: newPrestigeCount,
    prestigeMultiplier: 1 + newPrestigeCount * 0.1,
    ancestralDna: state.ancestralDna + dnaGained,
    lifetimeTadpoles: 0,
    lastTick: Date.now(),
    // evolutionTree persiste — jamais reset
  };
}

// Valeurs par défaut — 5 tiers alignés GDD Tetard Universe (x10 coût / tier)
export const DEFAULT_GENERATORS: Generator[] = [
  { id: "nid",       name: "Nid",            baseCost: 10,      baseProduction: 0.1,  owned: 0 },
  { id: "mare",      name: "Mare",           baseCost: 100,     baseProduction: 0.5,  owned: 0 },
  { id: "marecage",  name: "Marécage",       baseCost: 1_000,   baseProduction: 3,    owned: 0 },
  { id: "etang",     name: "Étang Ancien",   baseCost: 10_000,  baseProduction: 20,   owned: 0 },
  { id: "lac",       name: "Lac Mystique",   baseCost: 100_000, baseProduction: 150,  owned: 0 },
];

export const DEFAULT_STATE: GameState = {
  resources: 0,
  clickMultiplier: 1,
  generators: DEFAULT_GENERATORS,
  lastTick: Date.now(),
  prestigeCount: 0,
  prestigeMultiplier: 1,
  ancestralDna: 0,
  evolutionTree: DEFAULT_EVOLUTION_TREE,
  lifetimeTadpoles: 0,
};
