using CaseAccountingContracts.BindingModels;
using CaseAccountingContracts.ViewModels;
using CaseAccountingDataModels.Models;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace CaseAccountingDataBaseImplement.Models
{
    public class Case : ICaseModel
    {
        public int Id { get; set; }

        [Required]
        public string Name { get; set; } = string.Empty;

        [Required]
        public string Applicant { get; set; } = string.Empty;

        [Required]
        public string Defendant { get; set; } = string.Empty;

        [Required]
        public string Annotation { get; set; } = string.Empty;

        [Required]
        public DateTime Date { get; set; }

        [Required]
        public int SpecializationId { get; set; }

        public virtual Specialization Specialization { get; set; } = new();

        [Required]
        public int UserId { get; set; }

        public virtual User User { get; set; } = new();

        [ForeignKey("CaseId")]
        public virtual List<Hearing> Hearings { get; set; } = new();

        [ForeignKey("CaseId")]
        public virtual List<CaseLawyer> CaseLawyers { get; set; } = new();

        private Dictionary<int, ILawyerModel>? _lawyers;

        [NotMapped]
        public Dictionary<int, ILawyerModel> Lawyers
        {
            get
            {
                if (_lawyers == null)
                {
                    _lawyers = CaseLawyers.ToDictionary(
                        x => x.LawyerId, x => x.Lawyer as ILawyerModel);
                }
                return _lawyers;
            }
        }

        [ForeignKey("CaseId")]
        public virtual List<CaseDeal> Deals { get; set; } = new();

        public static Case? Create(CaseAccountingDatabase context, CaseBindingModel model)
        {
            if (model == null)
            {
                return null;
            }
            return new Case()
            {
                Id = model.Id,
                Name = model.Name,
                Applicant = model.Applicant,
                Defendant = model.Defendant,
                Annotation = model.Annotation,
                Date = model.Date,
                SpecializationId = model.SpecializationId,
                Specialization = context.Specializations.FirstOrDefault( x => x.Id == model.SpecializationId) ?? throw new Exception("Specialization не существует"),
                UserId = model.UserId,
                User = context.Users.FirstOrDefault(x => x.Id == model.UserId) ?? throw new Exception("User не существует")
			};
        }

        public void Update(CaseAccountingDatabase context, CaseBindingModel model)
        {
            if (model == null)
            {
                return;
            }
            Name = model.Name;
            Applicant = model.Applicant;
            Defendant = model.Defendant;
            SpecializationId = model.SpecializationId;
            Specialization = context.Specializations.FirstOrDefault(x => x.Id == model.SpecializationId) ?? throw new Exception("Specialization не существует");
            Annotation = model.Annotation;
            Date = DateTime.SpecifyKind(model.Date, DateTimeKind.Utc);
        }

        public void UpdateLawyers(CaseAccountingDatabase context, CaseBindingModel model)
        {
            var caseLawyers = context.CaseLawyers
                .Where(x => x.CaseId == model.Id)
                .ToList();
            if (caseLawyers != null)
            {
                context.CaseLawyers
                    .RemoveRange(caseLawyers
                            .Where(x => !model.Lawyers
                            .ContainsKey(x.LawyerId))
                        );
                context.SaveChanges();
                var _case = context.Cases
                    .First(x => x.Id == Id);
                foreach (var cl in caseLawyers)
                {
                    model.Lawyers.Remove(cl.LawyerId);
                }
                foreach (var cl in model.Lawyers)
                {
                    context.CaseLawyers.Add(new CaseLawyer
                    {
                        Case = _case,
                        Lawyer = context.Lawyers.First(x => x.Id == cl.Key),
                    });
                    context.SaveChanges();
                }
                _lawyers = null;
            }
        }

        public CaseViewModel GetViewModel => new()
        {
            Id = Id,
            Name = Name,
            Applicant = Applicant,
            Defendant = Defendant,
            Annotation = Annotation,
            Date = Date,
            SpecializationId = SpecializationId,
            Specialization = Specialization.Name,
            UserId = UserId
        };
    }
}
