using Baya.Domain.Common;

namespace Baya.Domain.Entities.Identity;

/// <summary>
/// A nurse's seller profile plus the denormalized search/quality aggregates. Separated from
/// <c>users</c> so the base identity row stays lean and the nurse-only attributes (and the aggregates
/// search reads on every query) live together. A profile is created unverified and not accepting
/// bookings — a nurse is not bookable until the b6 verification pipeline flips <see cref="IsVerified"/>.
/// </summary>
public class NurseProfile : BaseEntity<long>
{
    public int UserId { get; set; }
    public User.User User { get; set; }

    /// <summary>The licensed center legally sponsoring this nurse at launch (Asanism model). NULL once
    /// Balinyaar holds its own permit. Forward dependency on <c>partner_centers</c> (b15) — nullable,
    /// no FK target is enforced in this phase.</summary>
    public long? PartnerCenterId { get; set; }

    public string Bio { get; set; }
    public int YearsOfExperience { get; set; }
    public string EducationLevel { get; set; }
    public string EducationField { get; set; }
    public string SpecializationsJson { get; set; }

    /// <summary>Public URL of the nurse's profile photo, stored via <c>IObjectStorage</c>. NULL until the
    /// nurse uploads one. Denormalized into <c>nurse_search_index</c> for the discovery card.</summary>
    public string AvatarUrl { get; set; }

    /// <summary>Write-guarded. Flipped ONLY inside the b6 verification-confirm transaction once every
    /// required verification step has passed — never from a profile command in this phase. A nurse is
    /// not bookable until this is true.</summary>
    public bool IsVerified { get; private set; }

    /// <summary>Whether the nurse currently accepts new bookings. A nurse can pause without losing
    /// verified status — toggled via <see cref="SetAcceptingBookings"/>.</summary>
    public bool IsAcceptingBookings { get; private set; }

    /// <summary>Denormalized read-only aggregate. Defaults to 0; recomputed by the reviews/bookings
    /// phases (b9/b14) — never accepted from a request in this phase.</summary>
    public decimal AverageRating { get; private set; }

    public int TotalReviews { get; private set; }
    public int TotalCompletedBookings { get; private set; }

    public DateTimeOffset? DeletedAt { get; set; }

    public ICollection<NurseBankAccount> BankAccounts { get; set; }

    /// <summary>The single sanctioned write path for the guarded verified flag — called only by the b6
    /// verification-confirm transaction.</summary>
    public void MarkVerified() => IsVerified = true;

    public void MarkUnverified() => IsVerified = false;

    public void SetAcceptingBookings(bool accepting) => IsAcceptingBookings = accepting;

    /// <summary>The single sanctioned write path for the denormalized rating aggregates — called only by the
    /// b14 reviews phase, which recomputes both values from source (published reviews only) on every
    /// moderation transition. Never accepted from a request.</summary>
    public void SetReviewAggregates(decimal averageRating, int totalReviews)
    {
        AverageRating = averageRating;
        TotalReviews = totalReviews;
    }
}
