using System;
using System.Collections.Generic;
namespace VanadiumGuard.Server.Bans
{
/// One machine as the service knows it, and every account seen on it.
public sealed class MachineRecord
{
public string Composite { get; set; } = string.Empty;
///
/// The component hashes this machine reported. Kept so a ban can still recognise the
/// machine after one part is swapped and the composite changes.
///
public Dictionary Components { get; set; } = new Dictionary(StringComparer.Ordinal);
/// Accounts that have opened a guard session from this machine.
public List PlayerIds { get; set; } = new List();
public DateTimeOffset FirstSeenUtc { get; set; }
public DateTimeOffset LastSeenUtc { get; set; }
/// Null when the machine is not banned. A lifted ban is removed, not flagged.
public MachineBan? Ban { get; set; }
}
///
/// A hardware ban.
///
/// Every field here exists to answer a question someone will eventually ask about this
/// record: who did it, when, why, and until when. A ban list with no answers to those is
/// a liability rather than a tool - the appeal that cannot be evaluated gets denied by
/// default, which is the failure mode worth engineering against.
///
///
public sealed class MachineBan
{
public string Reason { get; set; } = string.Empty;
/// Identity of the moderator or system that issued it, recorded verbatim.
public string IssuedBy { get; set; } = string.Empty;
public DateTimeOffset IssuedUtc { get; set; }
/// Null bans permanently.
public DateTimeOffset? ExpiresUtc { get; set; }
///
/// The accounts linked to the machine when the ban was issued. A snapshot, so the
/// reviewer can see what the moderator was looking at rather than what the link
/// table happens to say today.
///
public List LinkedPlayerIdsAtIssue { get; set; } = new List();
public bool IsActive(DateTimeOffset now)
{
return ExpiresUtc == null || ExpiresUtc > now;
}
}
}