using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Fitness_core_BE.Models
{
public class CustomerPlan
{
[Key]
public Guid CustomerPlanId { get; set; }
public Guid FKClientId { get; set; }
[ForeignKey("FKClientId")]
public virtual Client Client { get; set; }
public string? PlanName { get; set; }
public string? PlanDescription { get; set; }
public decimal PlanPrice { get; set; }
/// Whether this plan charges a one-time fee when a new subscription starts.
public bool HasOnboardingFee { get; set; } = false;
/// One-time amount added to the first invoice/installment.
public decimal OnboardingFeeAmount { get; set; } = 0m;
/// Used when DurationMode == "Rolling"; 0 for FixedRange plans.
public int DurationInDays { get; set; }
/// "Individual" | "Group" (couple/family — one subscription covers MemberLimit members).
public string PlanScope { get; set; } = "Individual";
/// 1 for Individual; >= 2 for Group (couple = 2).
public int MemberLimit { get; set; } = 1;
/// "Rolling" (DurationInDays from join date) | "FixedRange" (ValidFrom–ValidTo).
public string DurationMode { get; set; } = "Rolling";
public DateTime? ValidFrom { get; set; }
public DateTime? ValidTo { get; set; }
/// Owner decides: when true the price splits into InstallmentCount scheduled parts.
public bool AllowSplitPayments { get; set; } = false;
/// Number of mostly-equal installments (1 = full payment upfront).
public int InstallmentCount { get; set; } = 1;
/// Null = unlimited-access plan (existing gym behavior). A number = this plan
/// grants that many bookable Facility sessions per billing cycle (e.g. "4 pool sessions
/// a month") — enforced by the booking flow, not by this model.
public int? SessionsPerCycle { get; set; }
/// "NoRollover" (unused sessions are forfeited when the cycle renews) |
/// "GracePeriod" (unused sessions stay usable for RolloverGraceDays after renewal).
/// Set per package at creation time, per owner's requirement.
public string SessionRolloverPolicy { get; set; } = "NoRollover";
/// Days into the new cycle that last cycle's unused sessions remain usable.
/// Only meaningful when SessionRolloverPolicy == "GracePeriod".
public int RolloverGraceDays { get; set; } = 0;
/// "Prepaid" (pay before the cycle starts, existing behavior) | "Postpaid"
/// (use first, invoice at cycle end — reuses Client.LockAfterDaysOverdue /
/// OverdueLockJob to suspend access if that invoice goes unpaid past due). Asked once,
/// per package, at creation time per owner's requirement.
public string BillingTiming { get; set; } = "Prepaid";
public bool IsActive { get; set; } = true;
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
/// Meaningful only for a plan linked to one or more classes (via
/// CustomerPlanClass) -- never consulted for an ordinary plan with no class links,
/// which always grants gym access regardless of this flag's stored value. Lets a class
/// plan optionally also grant general gym-floor access ("class + gym" as one product)
/// instead of class-only. Migration default true (so every pre-existing plan, which has
/// no class links, keeps behaving exactly as before); new class plans default this to
/// false in the UI.
public bool GrantsGymAccess { get; set; } = true;
}
}