using Data.SeaHavenIndustries.Enums; using SeaHaven.Services.Interfaces; namespace SeaHaven.Services.Implementation { public class WorkOrderStatusMapper : IWorkOrderStatusMapper { private static readonly HashSet TerminalCanonical = new(StringComparer.OrdinalIgnoreCase) { nameof(WorkOrderStatus.Completed), nameof(WorkOrderStatus.Cancelled), }; private static readonly Dictionary DbToCanonical = new(StringComparer.OrdinalIgnoreCase) { ["Open"] = nameof(WorkOrderStatus.Open), ["new"] = nameof(WorkOrderStatus.Open), ["assigned"] = nameof(WorkOrderStatus.Open), ["unknown"] = nameof(WorkOrderStatus.Open), ["UnAssigned"] = nameof(WorkOrderStatus.Open), ["Unassigned"] = nameof(WorkOrderStatus.Open), ["In Progress"] = nameof(WorkOrderStatus.InProgress), ["InProgress"] = nameof(WorkOrderStatus.InProgress), ["in_progress"] = nameof(WorkOrderStatus.InProgress), ["On Hold"] = nameof(WorkOrderStatus.OnHold), ["OnHold"] = nameof(WorkOrderStatus.OnHold), ["on_hold"] = nameof(WorkOrderStatus.OnHold), ["Done"] = nameof(WorkOrderStatus.Completed), ["Completed"] = nameof(WorkOrderStatus.Completed), ["completed"] = nameof(WorkOrderStatus.Completed), ["Cancelled"] = nameof(WorkOrderStatus.Cancelled), ["cancelled"] = nameof(WorkOrderStatus.Cancelled), ["Canceled"] = nameof(WorkOrderStatus.Cancelled), }; private static readonly Dictionary CanonicalToDisplay = new(StringComparer.OrdinalIgnoreCase) { [nameof(WorkOrderStatus.Open)] = "Scheduled", [nameof(WorkOrderStatus.InProgress)] = "In Progress", [nameof(WorkOrderStatus.OnHold)] = "Pending", [nameof(WorkOrderStatus.Completed)] = "Completed", [nameof(WorkOrderStatus.Cancelled)] = "Canceled", }; private static readonly Dictionary CanonicalToStorage = new(StringComparer.OrdinalIgnoreCase) { [nameof(WorkOrderStatus.Open)] = "Open", [nameof(WorkOrderStatus.InProgress)] = "In Progress", [nameof(WorkOrderStatus.OnHold)] = "On Hold", [nameof(WorkOrderStatus.Completed)] = "Done", [nameof(WorkOrderStatus.Cancelled)] = "Cancelled", }; private static readonly Dictionary DisplayToCanonical = new(StringComparer.OrdinalIgnoreCase) { ["Incomplete"] = nameof(WorkOrderStatus.Open), ["Pending"] = nameof(WorkOrderStatus.OnHold), ["Scheduled"] = nameof(WorkOrderStatus.Open), ["En Route"] = nameof(WorkOrderStatus.InProgress), ["On Site"] = nameof(WorkOrderStatus.InProgress), ["In Progress"] = nameof(WorkOrderStatus.InProgress), ["Completed"] = nameof(WorkOrderStatus.Completed), ["Rescheduled"] = nameof(WorkOrderStatus.Open), ["Canceled"] = nameof(WorkOrderStatus.Cancelled), ["Cancelled"] = nameof(WorkOrderStatus.Cancelled), ["Pending Quote"] = nameof(WorkOrderStatus.OnHold), ["Open"] = nameof(WorkOrderStatus.Open), ["On Hold"] = nameof(WorkOrderStatus.OnHold), ["Done"] = nameof(WorkOrderStatus.Completed), ["Unassigned"] = nameof(WorkOrderStatus.Open), ["UnAssigned"] = nameof(WorkOrderStatus.Open), }; public string NormalizeToCanonical(string? dbStatus) { if (string.IsNullOrWhiteSpace(dbStatus)) return nameof(WorkOrderStatus.Open); var trimmed = dbStatus.Trim(); if (DbToCanonical.TryGetValue(trimmed, out var canonical)) return canonical; if (Enum.TryParse(trimmed, ignoreCase: true, out var parsed)) return parsed.ToString(); return nameof(WorkOrderStatus.Open); } public string ToDisplay(string canonical, bool isUnassigned = false) { if (isUnassigned && string.Equals(canonical, nameof(WorkOrderStatus.Open), StringComparison.OrdinalIgnoreCase)) return "Incomplete"; if (CanonicalToDisplay.TryGetValue(canonical, out var display)) return display; return canonical; } public bool IsTerminal(string canonical) { return TerminalCanonical.Contains(canonical); } public IReadOnlyList ExpandCanonicalForFilter(string canonical) { var normalized = NormalizeToCanonical(canonical); return normalized switch { nameof(WorkOrderStatus.Open) => new[] { "Open", "UnAssigned", "Unassigned", "new", "assigned", "unknown" }, nameof(WorkOrderStatus.InProgress) => new[] { "In Progress", "InProgress", "in_progress" }, nameof(WorkOrderStatus.OnHold) => new[] { "On Hold", "OnHold", "on_hold" }, nameof(WorkOrderStatus.Completed) => new[] { "Done", "Completed", "completed" }, nameof(WorkOrderStatus.Cancelled) => new[] { "Cancelled", "cancelled", "Canceled" }, _ => new[] { normalized }, }; } public IReadOnlyList ExpandCanonicalFilters(IEnumerable? canonicalStatuses) { if (canonicalStatuses == null) return Array.Empty(); return canonicalStatuses .Where(s => !string.IsNullOrWhiteSpace(s)) .SelectMany(ExpandCanonicalForFilter) .Distinct(StringComparer.OrdinalIgnoreCase) .ToList(); } public string ToStorage(string canonical) { var normalized = NormalizeToCanonical(canonical); return CanonicalToStorage.TryGetValue(normalized, out var storage) ? storage : normalized; } public string? FromDisplay(string? statusDisplay) { if (string.IsNullOrWhiteSpace(statusDisplay)) return null; if (DisplayToCanonical.TryGetValue(statusDisplay.Trim(), out var canonical)) return ToStorage(canonical); return ToStorage(NormalizeToCanonical(statusDisplay)); } } }