Game/Idle/IdleAchievements.cs
using System;
using System.Collections.Generic;
using System.Linq;

/// <summary>
/// The Reactor Log — long-tail goals that hand out Flux and Fragments.
/// These are the "one more session" hooks: each one is visible from the start
/// with a progress bar, so there is always something a few minutes away.
/// </summary>
public class IdleAchievement
{
	public string Id    { get; set; }
	public string Name  { get; set; }
	public string Icon  { get; set; }
	public string Desc  { get; set; }

	public int RewardFlux  { get; set; }
	public int RewardFrags { get; set; }

	/// <summary>Current progress, 0..Target.</summary>
	public Func<IdleSave, double> Progress { get; set; }
	public double Target { get; set; }

	/// <summary>True when the numeric target should be shown compacted (big currency).</summary>
	public bool BigNumbers { get; set; }

	public bool IsDone( IdleSave s ) => Progress( s ) >= Target;

	public float Fraction( IdleSave s )
		=> Target <= 0 ? 1f : (float)Math.Clamp( Progress( s ) / Target, 0.0, 1.0 );
}

public static class IdleAchievements
{
	public static readonly List<IdleAchievement> All = new()
	{
		// ── First steps ──
		new IdleAchievement { Id = "first_blood", Name = "Ignition", Icon = "🔥",
			Desc = "Run 25 detonation cycles.",
			Progress = s => s.TotalDetonations, Target = 25, RewardFrags = 5 },

		new IdleAchievement { Id = "cores_1k", Name = "Warm Start", Icon = "⚛️",
			Desc = "Bank 1,000 Cores in one cycle.",
			Progress = s => s.CycleCores, Target = 1_000, BigNumbers = true, RewardFrags = 8 },

		new IdleAchievement { Id = "chain_10", Name = "Linked", Icon = "⛓️",
			Desc = "Clear 10 chests in a single detonation.",
			Progress = s => s.BestChain, Target = 10, RewardFrags = 10 },

		// ── Getting going ──
		new IdleAchievement { Id = "cores_100k", Name = "Producer", Icon = "🏭",
			Desc = "Bank 100K Cores in one cycle.",
			Progress = s => s.CycleCores, Target = 100_000, BigNumbers = true, RewardFlux = 2, RewardFrags = 15 },

		new IdleAchievement { Id = "chain_25", Name = "Cascade", Icon = "🌊",
			Desc = "Clear 25 chests in a single detonation.",
			Progress = s => s.BestChain, Target = 25, RewardFlux = 1, RewardFrags = 15 },

		new IdleAchievement { Id = "golden_10", Name = "Quick Hands", Icon = "🌟",
			Desc = "Catch 10 Golden Chests.",
			Progress = s => s.GoldenGrabbed, Target = 10, RewardFrags = 20 },

		new IdleAchievement { Id = "blown_5k", Name = "Demolition Crew", Icon = "💣",
			Desc = "Destroy 5,000 chests in the reactor.",
			Progress = s => s.TotalChestsBlown, Target = 5_000, BigNumbers = true, RewardFrags = 25 },

		// ── The prestige wall ──
		new IdleAchievement { Id = "meltdown_1", Name = "Critical", Icon = "☢️",
			Desc = "Trigger your first Meltdown.",
			Progress = s => s.Meltdowns, Target = 1, RewardFlux = 3, RewardFrags = 40 },

		new IdleAchievement { Id = "meltdown_5", Name = "Serial Offender", Icon = "🔁",
			Desc = "Trigger 5 Meltdowns.",
			Progress = s => s.Meltdowns, Target = 5, RewardFlux = 10, RewardFrags = 60 },

		new IdleAchievement { Id = "flux_50", Name = "Fluxed", Icon = "🔷",
			Desc = "Earn 50 Flux in total.",
			Progress = s => s.FluxEarned, Target = 50, RewardFrags = 50 },

		// ── Long haul ──
		new IdleAchievement { Id = "cps_10k", Name = "Ten Thousand A Second", Icon = "📈",
			Desc = "Reach 10K Cores per second.",
			Progress = s => s.BestCps, Target = 10_000, BigNumbers = true, RewardFlux = 5, RewardFrags = 50 },

		new IdleAchievement { Id = "chain_60", Name = "Board Wipe", Icon = "🧨",
			Desc = "Clear 60 chests in a single detonation.",
			Progress = s => s.BestChain, Target = 60, RewardFlux = 6, RewardFrags = 60 },

		new IdleAchievement { Id = "cores_1b", Name = "Billionaire", Icon = "💎",
			Desc = "Bank 1B Cores in one cycle.",
			Progress = s => s.CycleCores, Target = 1e9, BigNumbers = true, RewardFlux = 15, RewardFrags = 100 },

		new IdleAchievement { Id = "runtime_2h", Name = "Shift Worker", Icon = "🕒",
			Desc = "Watch the reactor for 2 hours total.",
			Progress = s => s.SecondsRun, Target = 7_200, RewardFrags = 40 },

		new IdleAchievement { Id = "runtime_10h", Name = "Reactor Chief", Icon = "🎖️",
			Desc = "Watch the reactor for 10 hours total.",
			Progress = s => s.SecondsRun, Target = 36_000, RewardFlux = 12, RewardFrags = 120 },

		new IdleAchievement { Id = "alltime_1t", Name = "Chain Reaction", Icon = "♾️",
			Desc = "Produce 1T Cores across all cycles.",
			Progress = s => s.AllTimeCores, Target = 1e12, BigNumbers = true, RewardFlux = 40, RewardFrags = 250 },
	};

	/// <summary>
	/// Marks any newly completed achievement and returns them so the HUD can toast.
	/// Rewards are applied by the caller (it owns PlayerSave).
	/// </summary>
	public static List<IdleAchievement> CollectNewlyCompleted( IdleSave s )
	{
		List<IdleAchievement> done = null;

		foreach ( var a in All )
		{
			if ( s.HasAchievement( a.Id ) ) continue;
			if ( !a.IsDone( s ) ) continue;

			s.Achievements.Add( a.Id );
			(done ??= new()).Add( a );
		}

		return done ?? new List<IdleAchievement>();
	}

	public static int CompletedCount( IdleSave s ) => All.Count( a => s.HasAchievement( a.Id ) );
}