// 回响星核 / Echo Nexus — 核心引擎：产能聚合、技术效果、飞升
import type { GameState, PrestigeBonus, ResonanceColor, CrystalTier } from "./types";
import {
  INITIAL_STATE,
  TECH_TREE,
  PRESTIGE,
  CRYSTAL_VALUE,
  CONTACT,
} from "./config";
import { achievementBonuses } from "./achievements";

/** 由技术树 + 飞升蓝图 + 成就聚合计算产能字段 */
export function recomputeStats(state: Partial<GameState>): {
  crystalsPerSec: number;
  crystalCap: number;
  pulsePower: number;
  offlineEff: number;
  insightMult: number;
  contactRateMult: number;
  autoDecode: boolean;
  decodeStepsBonus: number;
} {
  const tech = state.tech ?? {};
  const bp = state.blueprints?.length ?? 0;
  const ach = achievementBonuses(state.achievements ?? {});

  let crystalsPerSec = INITIAL_STATE.crystalsPerSec;
  let crystalCap = INITIAL_STATE.crystalCap;
  let pulsePower = INITIAL_STATE.pulsePower;
  let offlineEff = INITIAL_STATE.offlineEff;
  let insightMult = INITIAL_STATE.insightMult;
  let contactRateMult = 1;
  let autoDecode = false;
  let decodeStepsBonus = 0;

  for (const node of TECH_TREE) {
    const lvl = tech[node.id] ?? 0;
    if (!lvl) continue;
    const eff = node.effect;
    switch (eff.kind) {
      case "crystalsPerSec":
        crystalsPerSec += eff.value * lvl;
        break;
      case "crystalCap":
        crystalCap += eff.value * lvl;
        break;
      case "pulsePower":
        pulsePower += eff.value * lvl;
        break;
      case "offlineEff":
        offlineEff = Math.min(1, offlineEff + eff.value * lvl);
        break;
      case "insightMult":
        insightMult += eff.value * lvl;
        break;
      case "contactRate":
        contactRateMult += eff.value * lvl;
        break;
      case "decodeSteps":
        decodeStepsBonus += eff.value * lvl;
        break;
      case "autoDecode":
        autoDecode = lvl > 0;
        break;
    }
  }

  // 飞升蓝图加成
  crystalsPerSec *= 1 + bp * PRESTIGE.perBlueprint.crystalsPerSecMult;
  insightMult *= 1 + bp * PRESTIGE.perBlueprint.insightMult;
  contactRateMult *= 1 + bp * PRESTIGE.perBlueprint.contactRateMult;

  // 成就永久加成（跨周目）
  crystalsPerSec *= 1 + ach.crystalsPerSecPct / 100;
  insightMult *= 1 + ach.insightPct / 100;

  return {
    crystalsPerSec,
    crystalCap,
    pulsePower,
    offlineEff,
    insightMult,
    contactRateMult,
    autoDecode,
    decodeStepsBonus,
  };
}

/** 计算飞升加成概览（展示用） */
export function computePrestigeBonus(state: GameState): PrestigeBonus {
  const bp = state.blueprints.length;
  return {
    crystalsPerSecMult: bp * PRESTIGE.perBlueprint.crystalsPerSecMult,
    insightMult: bp * PRESTIGE.perBlueprint.insightMult,
    contactRateMult: bp * PRESTIGE.perBlueprint.contactRateMult,
  };
}

/** 本次飞升可获得的蓝图数 */
export function computeNewBlueprints(state: GameState): number {
  const earned = Math.floor(state.totalDecoded / PRESTIGE.blueprintsPerDecode);
  return Math.max(0, Math.min(PRESTIGE.maxBlueprints, earned) - state.blueprints.length);
}

/** 执行飞升：重置数值，保留蓝图与图谱与成就与部分技术 */
export function performPrestige(state: GameState): GameState {
  const newBp = computeNewBlueprints(state);
  const blueprints = [
    ...state.blueprints,
    ...Array.from({ length: newBp }, (_, i) => `bp_${Date.now()}_${i}`),
  ].slice(0, PRESTIGE.maxBlueprints);

  // 保留：fragments, totalDecoded(累计), ascensions+1, blueprints, achievements, theme/sound, expeditionLog
  // 重置：资源、技术、产能、pendingCrystals、activePuzzle、activeExpedition、contact、lastTick、energy
  const fresh = createInitialState();
  const stats = recomputeStats({ tech: {}, blueprints, achievements: state.achievements });
  return {
    ...fresh,
    fragments: state.fragments,
    totalDecoded: state.totalDecoded,
    ascensions: state.ascensions + 1,
    blueprints,
    achievements: state.achievements,
    theme: state.theme,
    soundOn: state.soundOn,
    createdAt: state.createdAt,
    lastTick: Date.now(),
    lastEnergyTick: Date.now(),
    expeditionLog: state.expeditionLog,
    totalExpeditions: state.totalExpeditions,
    ...stats,
  };
}

/** 创建初始状态 */
export function createInitialState(): GameState {
  return {
    ...INITIAL_STATE,
    tech: {},
    fragments: {},
    achievements: {},
    pendingCrystals: [],
    activePuzzle: null,
    activeExpedition: null,
    expeditionLog: [],
    lastEnergyTick: Date.now(),
    createdAt: Date.now(),
    lastTick: Date.now(),
  } as GameState;
}

/** 计算解码奖励 */
export function decodeRewards(
  tier: CrystalTier,
  insightMult: number,
  contactRateMult: number
): { crystals: number; insights: number; contact: number } {
  const base = CRYSTAL_VALUE[tier];
  return {
    crystals: base.crystals,
    insights: Math.ceil(base.insights * insightMult),
    contact: +(CONTACT.basePerDecode * tier * contactRateMult).toFixed(2),
  };
}

/** 离线收益计算 */
export function computeOfflineGain(
  state: GameState,
  now: number
): { gain: number; seconds: number; capped: boolean } {
  const elapsed = Math.max(0, (now - state.lastTick) / 1000);
  const cap = 8 * 3600; // 8h
  const seconds = Math.min(elapsed, cap);
  const gain = state.crystalsPerSec * seconds * state.offlineEff;
  return { gain, seconds, capped: elapsed > cap };
}

/** 生成一颗晶体（按 tier 权重） */
export function rollCrystalTier(rng: () => number = Math.random): CrystalTier {
  const r = rng();
  if (r < 0.7) return 1;
  if (r < 0.95) return 2;
  return 3;
}

export type { ResonanceColor };
