namespace ClaudeDo.Data.Models;
///
/// The optional local-time window restricting when PowerUse applies
/// ( / End, both HH:mm).
/// Pure on purpose — the caller supplies "now", so the window logic is testable without a clock.
///
public static class PowerUseWindow
{
/// Parses an HH:mm string; anything else (including null/blank) is null.
public static TimeOnly? Parse(string? value)
=> TimeOnly.TryParseExact(value?.Trim(), "HH:mm", out var t) ? t : null;
/// Round-trips a stored/typed value through , so an unparseable
/// string is stored as null instead of sitting in the column pretending to be a window.
public static string? Normalize(string? value) => Parse(value)?.ToString("HH:mm");
///
/// True when falls inside the window. Half-open: start is included,
/// end is not. Either bound missing = no window at all = always true (the pre-window
/// behaviour). A window whose end is before its start wraps over midnight.
///
public static bool Contains(TimeOnly now, TimeOnly? start, TimeOnly? end)
{
if (start is not { } from || end is not { } to) return true;
return from < to ? now >= from && now < to : now >= from || now < to;
}
/// Convenience overload for the two stored strings and a wall clock.
public static bool IsOpen(DateTime now, string? start, string? end)
=> Contains(TimeOnly.FromDateTime(now), Parse(start), Parse(end));
}