using System;
using System.Globalization;
namespace ytLive.Models;
///
/// TASK 39·2: the three metrics that count towards YouTube Partner Program eligibility, as progress
/// towards the ad-revenue thresholds.
/// YouTube decides. This only reports what the published numbers say; it never claims
/// eligibility, and it cannot see strikes, AdSense state, 2FA or the review decision.
/// The view criteria are either/or — 4,000 public watch hours or 10M Shorts views —
/// so "2 of 3" is reported with that qualifier rather than implying all three must pass.
///
public sealed record YppProgress(
long Subscribers,
long SubscriberTarget,
long WatchHours,
long WatchHoursTarget,
long ShortsViews,
long ShortsViewsTarget)
{
public bool SubscribersMet => Subscribers >= SubscriberTarget;
public bool WatchHoursMet => WatchHours >= WatchHoursTarget;
public bool ShortsViewsMet => ShortsViews >= ShortsViewsTarget;
/// Criteria currently met (0–3). Two of three can mean eligible: subs plus EITHER view route.
public int CriteriaMet => (SubscribersMet ? 1 : 0) + (WatchHoursMet ? 1 : 0) + (ShortsViewsMet ? 1 : 0);
/// True when the subscriber bar AND at least one view route are satisfied — the shape of the
/// published rule. Still not a qualification claim: YouTube reviews it.
public bool MeetsPublishedRule => SubscribersMet && (WatchHoursMet || ShortsViewsMet);
public double SubscribersFraction => Fraction(Subscribers, SubscriberTarget);
public double WatchHoursFraction => Fraction(WatchHours, WatchHoursTarget);
public double ShortsViewsFraction => Fraction(ShortsViews, ShortsViewsTarget);
public string SubscribersText => $"{Compact(Subscribers)} / {Compact(SubscriberTarget)}";
public string WatchHoursText => $"{Compact(WatchHours)} / {Compact(WatchHoursTarget)} h";
public string ShortsViewsText => $"{Compact(ShortsViews)} / {Compact(ShortsViewsTarget)}";
public string CriteriaMetText => CriteriaMet == 1
? "1 of 3 criteria met — YouTube reviews eligibility."
: $"{CriteriaMet} of 3 criteria met — YouTube reviews eligibility.";
private static double Fraction(long value, long target)
=> target <= 0 ? 0 : Math.Clamp((double)value / target, 0, 1);
/// 1,234 → "1,234"; 12,345 → "12.3k"; 1,234,567 → "1.23M". Mono-face friendly and stable
/// in width, so the three bars do not jitter as values move.
internal static string Compact(long value) => value switch
{
>= 1_000_000 => (value / 1_000_000d).ToString("0.##", CultureInfo.InvariantCulture) + "M",
>= 10_000 => (value / 1_000d).ToString("0.#", CultureInfo.InvariantCulture) + "k",
_ => value.ToString("N0", CultureInfo.InvariantCulture),
};
}