using adas_core.Domain.Enums;
using adas_core.Domain.Models.MongoModels;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;

namespace adas_core.Domain.Models;

/// <summary>
/// Represents a patient observation, extending the base patient observation value functionality.
/// </summary>
/// <remarks>
/// This class serves as a concrete implementation of patient observation data, inheriting common observation value behavior from <see cref="BasePatientObservationValue"/>.
/// </remarks>
/// <!-- aidoc:v1 sig=877e2d3 -->
public class PatientObservation : BasePatientObservationValue
{
    private string? _result;

    /// <summary>
    /// Initializes a new default instance of the <see cref="PatientObservation"/> class, which represents a clinical observation recorded for a patient.
    /// </summary>
    /// <!-- aidoc:v1 sig=5c55204 body=4448e1d -->
    public PatientObservation()
    {
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="PatientObservation"/> class, which represents an observation linked to a patient, with the specified identifier, value, and name.
    /// </summary>
    /// <param name="patientId">The <see cref="ObjectId"/> identifying the patient associated with the observation.</param>
    /// <param name="value">The value recorded for the observation.</param>
    /// <param name="name">The name of the observation, or <see langword="null"/>.</param>
    /// <!-- aidoc:v1 sig=6b8c74d body=a32087f -->
    public PatientObservation(ObjectId patientId, object value, string? name)
    {
        PatientId = patientId;
        Value = value;
        Name = name;
    }

    public double? Max { get; set; }

    public double? Min { get; set; }

    public double? MaxWarn { get; set; }

    public double? MinWarn { get; set; }

    public string? WarnColor { get; set; }

    public string? AlertColor { get; set; }

    public bool ShowOnExpired { get; set; } = true;
    public ObservationEnum.InsertMode InsertMode { get; set; } = ObservationEnum.InsertMode.Auto;

    public bool? Persist { get; set; }

    public string? ColorOnExpired { get; set; }

    //MSH Time of HL7
    public DateTime MessageTime { get; set; }

    public string? Result
    {
        get => _result;
        set => _result = value == "F" ? null : value;
    }

    /// <summary>
    /// Returns a string representation of the <see cref="PatientObservation"/>, including its value, optional min/max/warning thresholds, result, status, expiration, and persistence settings. Optional properties are only included in the output when they have non-null or, for strings, non-empty values.
    /// </summary>
    /// <returns>A formatted string in the form <c>PatientObservation[property1: value1, ...]</c> containing the populated properties of the observation.</returns>
    /// <!-- aidoc-review:v1 severity=medium kind=stale_summary
    ///      "Summary omits the 'showOnExpired' and 'colorOnExpired' properties which are also conditionally added to the output." -->
    /// <!-- aidoc-review:v1 severity=medium kind=wrong_summary
    ///      "Summary states optional properties are included 'when they have non-null or, for strings, non-empty values', but 'showOnExpired' is added only when !ShowOnExpired (i.e., when the boolean is false)." -->
    public override string ToString()
    {
        var items = ToListString();
        items.Add($"value: {Value}");
        if (Max != null) items.Add($"max: {Max}");
        if (Min != null) items.Add($"min: {Min}");
        if (MaxWarn != null) items.Add($"maxWarn: {MaxWarn}");
        if (MinWarn != null) items.Add($"minWarn: {MinWarn}");
        if (!string.IsNullOrEmpty(Result)) items.Add($"result: {Result}");
        items.Add($"status: {Status}");
        if (Expires != null) items.Add($"expires: {Expires}");
        if (!ShowOnExpired) items.Add($"showOnExpired: {ShowOnExpired}");
        if (ColorOnExpired != null) items.Add($"colorOnExpired: {ColorOnExpired}");
        if (Persist != null) items.Add($"persist: {Persist}");
        return "PatientObservation[" + string.Join(", ", items) + "]";
    }

    /// <summary>
    /// Creates a copy of the current <see cref="PatientObservation"/> instance by performing a shallow copy via MemberwiseClone and casting the cloned object back to <see cref="PatientObservation"/>.
    /// </summary>
    /// <returns>A <see cref="PatientObservation"/> instance that is a shallow copy of the current object.</returns>
    /// <!-- aidoc:v1 sig=25ad808 body=6d4453e -->
    public PatientObservation DeepCopy()
    {
        return (PatientObservation)MemberwiseClone();
    }


    #region calculated properties

    public StatusEnum.Type Status { get; set; } = StatusEnum.Type.Ok;

    public int Level { get; set; }

    public int? Expires { get; set; } //seconds


    [BsonDefaultValue(false)] public bool Expired { get; set; }

    public Dictionary<string, object>? UiConfiguration { get; set; }

    public AlarmConfig? Alarm { get; set; }

    #endregion
}