using adas_core.Domain.Enums;
using adas_core.Domain.Models.MongoModels;

namespace adas_core.Domain.Models;

public class Person : IEquatable<Person>
{
    public string? LastName { get; set; }

    public string? FirstName { get; set; }

    public string? SecondName { get; set; }

    public DateTime? BirthDate { get; set; }

    public string? Language { get; set; }

    public PatientEnum.Gender Gender { get; set; } = PatientEnum.Gender.Unknown;

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


    public List<HistoricalId>? HistoricalIds { get; set; }

    public bool Equals(Person? other)
    {
        return other != null &&
               LastName == other.LastName &&
               FirstName == other.FirstName &&
               SecondName == other.SecondName &&
               BirthDate == other.BirthDate &&
               Language == other.Language &&
               Gender == other.Gender && CheckIdsAreEqual(other);
    }

    public void SetIds(Dictionary<string, string> patientIds, DateTime? time = null)
    {
        Ids = patientIds;
        HistoricalIds ??= new List<HistoricalId>();
    
        DateTime targetTime = time ?? DateTime.UtcNow;

        var existingOption = HistoricalIds.FirstOrDefault(c => c.Time == targetTime);

        if (existingOption != null)
        {
            foreach (var kvp in patientIds)
            {
                existingOption.PatientIds[kvp.Key] = kvp.Value;
            }
        }
        else
        {
            HistoricalIds.Add(new HistoricalId(targetTime, new Dictionary<string, string>(patientIds)));
        }
    }

    public bool IsEmpty()
    {
        return string.IsNullOrEmpty(LastName) && string.IsNullOrEmpty(FirstName) && string.IsNullOrEmpty(SecondName) &&
               BirthDate == null && Gender == PatientEnum.Gender.Unknown && (Ids == null || Ids.Count == 0);
    }

    public bool IsEmptyDontCheckIds()
    {
        return string.IsNullOrEmpty(LastName) && string.IsNullOrEmpty(FirstName) && string.IsNullOrEmpty(SecondName) &&
               BirthDate == null && Gender == PatientEnum.Gender.Unknown;
    }

    //public override bool Equals(object? obj)
    //{
    //    return Equals(obj as Person);
    //}

    private bool CheckIdsAreEqual(Person other)
    {
        if (Ids == null && other.Ids == null) return true;
        if (Ids == null || other.Ids == null) return false;
        if (Ids.Count != other.Ids.Count) return false;

        foreach (var kvp in Ids)
            if (!other.Ids.TryGetValue(kvp.Key, out var otherValue) || otherValue != kvp.Value)
                return false;
        return true;
    }

    //public override int GetHashCode()
    //{
    //    var hashCode = -373112803;
    //    if (LastName != null)
    //        hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(LastName);
    //    if (FirstName != null)
    //        hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(FirstName);
    //    if (SecondName != null)
    //        hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(SecondName);
    //    if (BirthDate != null) hashCode = hashCode * -1521134295 + BirthDate.GetHashCode();
    //    if (Language != null)
    //        hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(Language);
    //    hashCode = hashCode * -1521134295 + Gender.GetHashCode();
    //    if (Ids != null)
    //        hashCode = hashCode * -1521134295 + EqualityComparer<Dictionary<string, string>>.Default.GetHashCode(Ids);
    //    return hashCode;
    //}

    public override string ToString()
    {
        List<string> items = [];
        if (!string.IsNullOrEmpty(FirstName)) items.Add($"firstName: {FirstName}");
        if (!string.IsNullOrEmpty(LastName)) items.Add($", lastName: {LastName}");
        if (!string.IsNullOrEmpty(SecondName)) items.Add($"secondName: {SecondName}");
        if (BirthDate.HasValue) items.Add($"birthDate: {BirthDate}");
        if (!string.IsNullOrEmpty(Language)) items.Add($"language: {Language}");
        items.Add($"gender: {Gender}");
        if (Ids?.Count > 0) items.Add($"ids: {string.Join(',', Ids.Select(i => $"[{i.Key}:{i.Value}]"))}");
        return "Person[" + string.Join(", ", items) + "]";
    }
}