using Microsoft.EntityFrameworkCore;
using SVSim.Bootstrap.Models.Seed;
using SVSim.Database;
using SVSim.Database.Enums;
using SVSim.Database.Models;
namespace SVSim.Bootstrap.Importers;
///
/// Idempotent upsert of the per-pack draw table from
/// seeds/pack-draw-config.json, pack-draw-slot-rates.json, and
/// pack-draw-card-weights.json. Replaces wholesale per pack (config keyed on
/// pack_id; slot rates / card weights wiped and reinserted) — the upstream data is
/// post-shutdown closed, so we do not preserve hand-edits on these tables.
///
public class PackDrawTableImporter
{
public async Task ImportAsync(SVSimDbContext context, string seedDir)
{
var configs = SeedLoader.LoadList(Path.Combine(seedDir, "pack-draw-config.json"));
var slotRates = SeedLoader.LoadList(Path.Combine(seedDir, "pack-draw-slot-rates.json"));
var cardWeights = SeedLoader.LoadList(Path.Combine(seedDir, "pack-draw-card-weights.json"));
if (configs.Count == 0)
{
Console.WriteLine("[PackDrawTableImporter] No seed rows; skipping.");
return 0;
}
var seedPackIds = configs.Select(c => c.PackId).ToHashSet();
// Full-replace strategy: wipe rows for any pack in the seed, then reinsert.
await context.PackDrawCardWeights
.Where(w => seedPackIds.Contains(w.PackId))
.ExecuteDeleteAsync();
await context.PackDrawSlotRates
.Where(s => seedPackIds.Contains(s.PackId))
.ExecuteDeleteAsync();
var existingConfigs = await context.PackDrawConfigs
.Where(c => seedPackIds.Contains(c.Id))
.ToDictionaryAsync(c => c.Id);
foreach (var s in configs)
{
var row = existingConfigs.TryGetValue(s.PackId, out var ex)
? ex : new PackDrawConfigEntry { Id = s.PackId };
row.AnimationRatePct = s.AnimationRatePct;
row.HasBonusSlot = s.HasBonusSlot;
row.SpecialKind = s.SpecialKind;
row.ShortCode = s.ShortCode;
if (ex is null) context.PackDrawConfigs.Add(row);
}
foreach (var s in slotRates)
{
context.PackDrawSlotRates.Add(new PackDrawSlotRateEntry
{
PackId = s.PackId,
Slot = ParseSlot(s.Slot),
Tier = ParseTier(s.Tier),
RatePct = s.RatePct,
});
}
foreach (var s in cardWeights)
{
context.PackDrawCardWeights.Add(new PackDrawCardWeightEntry
{
PackId = s.PackId,
Slot = ParseSlot(s.Slot),
Tier = ParseTier(s.Tier),
CardId = s.CardId,
RatePct = s.RatePct,
IsLeader = s.IsLeader,
IsAltArt = s.IsAltArt,
});
}
await context.SaveChangesAsync();
Console.WriteLine($"[PackDrawTableImporter] {configs.Count} configs / {slotRates.Count} slot rates / {cardWeights.Count} card weights");
return configs.Count;
}
private static DrawSlot ParseSlot(string s) => s switch
{
"general" => DrawSlot.General,
"eighth" => DrawSlot.Eighth,
"bonus" => DrawSlot.Bonus,
_ => throw new InvalidDataException($"PackDrawTableImporter: unknown slot \"{s}\""),
};
private static DrawTier ParseTier(string s) => s switch
{
"bronze" => DrawTier.Bronze,
"silver" => DrawTier.Silver,
"gold" => DrawTier.Gold,
"legendary" => DrawTier.Legendary,
"special" => DrawTier.Special,
_ => throw new InvalidDataException($"PackDrawTableImporter: unknown tier \"{s}\""),
};
}