using adas_core.Domain.Enums;
using MongoDB.Bson;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace adas_core.Domain.Models;

public class PatientAppointment : JsonConverter
{
    public ObjectId Id { get; set; }

    public ObjectId PatientId { get; set; }

    public Person? Patient { get; set; }

    public List<Timing> Timings { get; set; } = [];

    public DateTime? CreateTime { get; set; }

    public DateTime UpdateTime { get; set; }

    public Entity? PlacerOrder { get; set; }

    public Entity? FillerOrder { get; set; }

    public string? EventReason { get; set; }

    public string? AppointmentReason { get; set; }

    public string? AppointmentType { get; set; }

    public OperationType? AppointmentOperationType { get; set; }

    public OperationType? AppointmentStatus { get; set; }

    public double Duration { get; set; }

    public string? VisitNumber { get; set; }

    public string? PatientClass { get; set; }

    public bool EpisodeActivation { get; set; } = false;

    public Person? PlacerContact { get; set; }

    public Person? FillerContact { get; set; }

    public List<PatientAppointmentResourceGroup> ResourceGroups { get; set; } = [];

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


    public List<PatientAppointmentResourceGroup> ApplyResourceGroups(PatientAppointment? apdb = null)
    {
        var i = 0;
        ResourceGroups = ResourceGroups.Select(rg =>
        {
            var rgdb = apdb != null && apdb.ResourceGroups.Count > i ? apdb.ResourceGroups[i] : null;

            rg.Services = CodeAction.Apply(rgdb?.Services, rg.ServicesActions);
            rg.Resources = CodeAction.Apply(rgdb?.Resources, rg.ResourcesActions);
            rg.Locations = PatientLocationAction.Apply(rgdb?.Locations, rg.LocationsActions);
            rg.Personnel = PersonResourceAction.Apply(rgdb?.Personnel, rg.PersonnelActions);
            return rg;
        }).ToList();
        return ResourceGroups;
    }

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(PatientAppointment);
    }

    public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
    {
        if (value != null)
        {
            var jo = JObject.FromObject(value);
            jo.Property("Id")?.Remove();
            jo.WriteTo(writer);
        }
    }

    public override object ReadJson(JsonReader reader, Type objectType, object? existingValue,
        JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

public class PatientAppointmentResourceGroup
{
    public List<Code>? Services { get; set; }

    public List<Code>? Resources { get; set; }

    public List<PatientLocation>? Locations { get; set; }

    public List<PersonResource>? Personnel { get; set; }

    /**
     * ApiRequest resource actions
     */
    public List<CodeAction>? ServicesActions { get; set; }

    public List<CodeAction>? ResourcesActions { get; set; }
    public List<PatientLocationAction>? LocationsActions { get; set; }
    public List<PersonResourceAction>? PersonnelActions { get; set; }
}

public class Allergies
{
    public Code? AllergenType { get; set; }

    public Code? Allergen { get; set; }
}