using Data.SeaHavenIndustries;
namespace SeaHaven.Services.Helpers
{
///
/// SH-379 / SH-190: single resolution for "the Site's live contact" used by the
/// manual POC override. The same rules back the board projection fallback, the
/// completion snapshot fallback, the create-time baseline, and the
/// "changing away from the contact the work order follows" lock comparison.
///
public static class WorkOrderPocSiteContact
{
///
/// The Site's primary live contact: first non-deleted contact ordered by
/// SiteContactOrder then Id. Null when the site has no live contacts.
///
public static Contacts? ResolvePrimary(IEnumerable? contacts)
=> contacts?
.Where(c => c.IsDeleted != true)
.OrderBy(c => c.SiteContactOrder)
.ThenBy(c => c.Id)
.FirstOrDefault();
/// Display name matching the board projection: trimmed First + Last.
public static string? DisplayName(Contacts? contact)
=> contact == null
? null
: Normalize(((contact.FirstName ?? "") + " " + (contact.LastName ?? "")).Trim());
///
/// SH-190: true when a manual POC (trimmed name + phone) equals the single
/// contact the work order currently follows — the linked WorkOrderContacts
/// POC, or else the Site primary. Such an edit is not a change away from
/// that contact, so it must not lock or store an override. Comparing against
/// only the followed contact (rather than any live Site contact) means an
/// edit to a different live contact is still stored, since the work order
/// only ever displays the one it follows.
///
public static bool Matches(string? name, string? phone, Contacts? contact)
{
if (contact == null)
return false;
return string.Equals(DisplayName(contact), Normalize(name), StringComparison.Ordinal)
&& string.Equals(Normalize(contact.PhoneNumber), Normalize(phone), StringComparison.Ordinal);
}
private static string? Normalize(string? value)
=> string.IsNullOrWhiteSpace(value) ? null : value.Trim();
}
}