using SVSim.Database.Enums;
using SVSim.Database.Models;
namespace SVSim.Database.Services.RankProgress;
///
/// Wire-shape result of a single rank-battle finish grant. The wire-mapped fields
/// (, , ,
/// , , ,
/// ) map 1:1 to RankBattleFinishResponseDto
/// keys the client reads via GetValueOrDefault in Wizard/RankBattleFinishTask.cs:57-63.
/// is a controller-side signal for the rank_achieved mission
/// emit and is not serialized to the wire.
///
/// rank_id post-grant (1..29).
/// Point post-grant (accumulated).
/// MasterPoint post-grant (accumulated).
/// Signed Point delta (+100/-50/0).
/// Signed MasterPoint delta.
/// True iff Rank == 25.
/// True iff Rank >= 26.
///
/// True iff this grant crossed the viewer into a higher bucket
/// than they held pre-grant. Callsites gate rank_achieved mission emits on this flag.
///
public sealed record RankProgressResult(
int Rank,
int AfterBattlePoint,
int AfterMasterPoint,
int BattlePoint,
int MasterPoint,
bool IsMasterRank,
bool IsGrandMasterRank,
bool TierAdvanced = false);
public interface IRankProgressService
{
///
/// Applies a +100 (win) or -50 (loss) delta to the viewer's rank progression in the
/// given format, respecting tier floors from ranks.csv's LowerLimitPoint column.
/// Creates a ViewerRankProgress row for (viewer, format) if none exists. Caller must
/// have loaded the viewer with .Include(v => v.RankProgress) and must call
/// SaveChangesAsync after this returns.
///
/// Must be Format.Rotation or Format.Unlimited.
Task GrantAsync(
Viewer viewer, Format format, bool isWin, CancellationToken ct = default);
///
/// Read-only current progression snapshot for (viewer, format). Returns a zero-value
/// result if no row exists. Does not mutate the viewer or hit the DB.
///
Task GetAsync(
Viewer viewer, Format format, CancellationToken ct = default);
}