using System.Text.Json.Serialization; namespace GoogleSheetsScheduleImport; /// /// JSON config: sheet tab titles mapped to calendar days plus optional defaults. /// public sealed class MappingConfig { /// Calendar year for occurrence dates (overridden by CLI --year). public int? Year { get; set; } /// /// Emitted before occurrence lines for each sheet (unless overridden per sheet). /// Use "General Schedule" when grid cells are generic schedule items. /// public string? DefaultSectionHeader { get; set; } /// Per-sheet overrides and day mapping. public List? Sheets { get; set; } /// /// Event titles (cell text) to treat as site-wide: one output line per date+time, no location. /// If omitted, built-in rules still include CURFEW. /// public List? SiteWideEventNames { get; set; } /// /// Path to event definitions CSV (column Event), relative to this mapping file or absolute. /// When set (or when --events-csv is passed), output is grouped into Event - MS/HS sections when possible. /// public string? EventDefinitionsCsv { get; set; } } public sealed class SheetDayMapping { /// Exact tab title as it appears in Google Sheets. public string Title { get; set; } = ""; /// Month name matching EventOccurrenceGrammar (e.g. "April"). public string Month { get; set; } = ""; /// Day of month (1-31). public int Day { get; set; } /// Optional section header line for this tab only (e.g. "General Schedule" or "Biotechnology - MS"). public string? SectionHeader { get; set; } [JsonIgnore] public string? NormalizedMonth => string.IsNullOrWhiteSpace(Month) ? null : Month.Trim(); public void Validate() { if (string.IsNullOrWhiteSpace(Title)) throw new InvalidOperationException("Mapping entry must include a non-empty Title (sheet tab name)."); if (string.IsNullOrWhiteSpace(Month)) throw new InvalidOperationException($"Sheet '{Title}': Month is required."); if (Day is < 1 or > 31) throw new InvalidOperationException($"Sheet '{Title}': Day must be between 1 and 31."); } }