using adas_core.Domain.Enums;
using MongoDB.Bson;

namespace adas_core.Domain.Models;

/// <summary>
/// Represents an observation that belongs to or has been categorized within a logical group.
/// </summary>
public class GroupedObservation
{
    public ObjectId PatientId { get; set; }
    public string? Name { get; set; } = string.Empty;

    public string? Group { get; set; } = string.Empty;

    public List<GroupedObservationObs> Observations { get; set; } = [];


    /// <summary>
    /// Returns a string representation of the PatientObservation, including the patient's name and observations in a formatted output.
    /// </summary>
    /// <returns>A formatted string in the form "PatientObservation[name: ..., observations: ...]".</returns>
    public override string ToString()
        {
            List<string> items =
            [
                $"name: {Name}",
                $"observations: {Observations} "
            ];
            return "PatientObservation[" + string.Join(", ", items) + "]";
        }

    /// <summary>
    /// Represents a grouped collection of observations.
    /// </summary>
    public class GroupedObservationObs
    {
        public string Name { get; set; } = string.Empty;

        public GroupedObservationObsValue? First { get; set; }

        public GroupedObservationObsValue? Last { get; set; }

        public GroupedObservationObsValue? Min { get; set; }

        public GroupedObservationObsValue? Max { get; set; }

        public object? MinAlert { get; set; }

        public object? MaxAlert { get; set; }

        public GroupedObservationObsValue? Average { get; set; }

        public GroupedObservationObsValue? Sum { get; set; }

        public GroupedObservationObsValue? Count { get; set; }

        public GroupedObservationObsValue? HalfHour { get; set; }

        public GroupedObservationObsValue? LastFilled { get; set; }

        public DateTime Time { get; set; }

        public int? Shift { get; set; }

        public DateTime ShiftDate { get; set; }

        public bool IsFilled { get; set; }

        /// <summary>
        /// Returns a string representation of the GroupedObservationObs, including the name and any non-null statistical properties (first, last, min, max, average, sum, count, half-hour, min alert, max alert), along with the time, shift date, and optional shift.
        /// </summary>
        /// <returns>A formatted string in the form "GroupedObservationObs[name: ..., ...]" summarizing the object's relevant properties.</returns>
        public override string ToString()
                {
                    List<string> items = [$"name: {Name}"];
                    if (First != null) items.Add($"first; {First}");
                    if (Last != null) items.Add($"last; {Last}");
                    if (Min != null) items.Add($"min; {Min}");
                    if (Max != null) items.Add($"max; {Max}");
                    if (Average != null) items.Add($"average; {Average}");
                    if (Sum != null) items.Add($"sum; {Sum}");
                    if (Count != null) items.Add($"count; {Count}");
                    if (HalfHour != null) items.Add($"halfhour; {HalfHour}");
                    if (MinAlert != null) items.Add($"minAlert; {MinAlert}");
                    if (MaxAlert != null) items.Add($"maxAlert; {MaxAlert}");
                    items.Add($"time; {Time}");
                    items.Add($"shiftDate; {ShiftDate}");
                    if (Shift != null) items.Add($"shift; {Shift}");
        
        
                    return "GroupedObservationObs[" + string.Join(", ", items) + "]";
                }
    }

    /// <summary>
    /// Represents an observed value within a grouped observation, pairing a value with an optional timestamp and status type.
    /// </summary>
    public class GroupedObservationObsValue(object value, DateTime? time, StatusEnum.Type type = StatusEnum.Type.Ok)
    {
        public StatusEnum.Type Type { get; set; } = type;

        public object Value { get; set; } = value;

        public DateTime? Time { get; set; } = time;


        /// <summary>
        /// Returns a formatted string representation of the object, including its value, time, and type/status fields.
        /// </summary>
        /// <returns>A string containing the value, time, and type of the object.</returns>
        public override string ToString()
                {
                    return $"value: {Value}, time: {Time}, status: {Type}";
                }
    }
}