namespace KArtSell.Modules.ModelOperations.Domain;
public readonly record struct LeaseFencingToken(long Value)
{
    public static LeaseFencingToken Next(LeaseFencingToken current) => new(checked(current.Value + 1));
}
public sealed class ModelOperationLease
{
    public string OperationCode { get; }
    public string ScopeKey { get; }
    public LeaseFencingToken Token { get; private set; }
    public DateTimeOffset ExpiresAt { get; private set; }
    public string Owner { get; private set; }
    public ModelOperationLease(string operationCode, string scopeKey, LeaseFencingToken token, string owner, DateTimeOffset expiresAt)
    {
        if (string.IsNullOrWhiteSpace(operationCode) || string.IsNullOrWhiteSpace(scopeKey) || string.IsNullOrWhiteSpace(owner)) throw new ArgumentException("Lease identity is required.");
        OperationCode=operationCode; ScopeKey=scopeKey; Token=token; Owner=owner; ExpiresAt=expiresAt;
    }
    public void Renew(LeaseFencingToken expectedToken, string owner, DateTimeOffset newExpiresAt)
    {
        if (expectedToken != Token || owner != Owner) throw new InvalidOperationException("Stale lease fencing token or owner.");
        if (newExpiresAt <= ExpiresAt) throw new InvalidOperationException("Lease renewal must extend expiry.");
        ExpiresAt=newExpiresAt;
    }
    public LeaseFencingToken Transfer(DateTimeOffset now, string newOwner, DateTimeOffset newExpiresAt)
    {
        if (now < ExpiresAt) throw new InvalidOperationException("Active lease cannot be transferred.");
        if (newExpiresAt <= now) throw new InvalidOperationException("New lease must expire in the future.");
        Token=LeaseFencingToken.Next(Token); Owner=newOwner; ExpiresAt=newExpiresAt; return Token;
    }
}
