using CandidateReviewContracts.BindingModels;
using CandidateReviewContracts.SearchModels;
using CandidateReviewContracts.StoragesContracts;
using CandidateReviewContracts.ViewModels;
using CandidateReviewDatabaseImplement.Models;
using CandidateReviewDataModels.Models;
using Microsoft.EntityFrameworkCore;

namespace CandidateReviewDatabaseImplement.Implements
{
    public class AssessmentStorage : IAssessmentStorage
    {
        public AssessmentViewModel? Delete(AssessmentBindingModel model)
        {
            using var context = new CandidateReviewDatabase();

            var element = context.Assessments
                .Include(x => x.User)
                .Include(x => x.Resume)
                .FirstOrDefault(rec => rec.Id == model.Id);

            if (element != null)
            {
                var relatedCriterions = context.AssessmentCriterions
                    .Where(x => x.AssessmentId == element.Id)
                    .ToList();

                context.AssessmentCriterions.RemoveRange(relatedCriterions);

                context.Assessments.Remove(element);

                context.SaveChanges();

                return element.GetViewModel;
            }

            return null;
        }

        public AssessmentViewModel? GetElement(AssessmentSearchModel model)
        {
            if (!model.Id.HasValue)
            {
                return null;
            }
            using var context = new CandidateReviewDatabase();
            if (model.ResumeId.HasValue && model.UserId.HasValue)
            {
                return context.Assessments
                .FirstOrDefault(x => x.ResumeId == model.ResumeId && x.UserId == model.UserId)
                ?.GetViewModel;
            }
            else if (model.ResumeId.HasValue)
            {
                return context.Assessments
                .FirstOrDefault(x => x.ResumeId == model.ResumeId)
                ?.GetViewModel;
            }
            else if (model.UserId.HasValue)
            {
                return context.Assessments
                .FirstOrDefault(x => x.UserId == model.UserId)
                ?.GetViewModel;
            }
            return context.Assessments
               .FirstOrDefault(x => model.Id.HasValue && x.Id == model.Id)
               ?.GetViewModel;
        }

        public List<AssessmentViewModel> GetFilteredList(AssessmentSearchModel model)
        {
            if (model is null)
            {
                return new();
            }
            using var context = new CandidateReviewDatabase();
            if (model.ResumeId.HasValue)
            {
                return context.Assessments
                .Where(x => x.ResumeId == model.ResumeId)
                .ToList()
                .Select(x => x.GetViewModel)
                .ToList();
            }

            if (model.UserId.HasValue)
            {
                return context.Assessments
                .Where(x => x.UserId == model.UserId)
                .ToList()
                .Select(x => x.GetViewModel)
                .ToList();
            }
            return context.Assessments
               .ToList()
               .Select(x => x.GetViewModel)
               .ToList();
        }

        public List<AssessmentViewModel> GetFullList()
        {
            using var context = new CandidateReviewDatabase();

            return context.Assessments
                .Include(x => x.User)
                .Include(x => x.Resume)
                .Select(x => x.GetViewModel).ToList();
        }

        public int? Insert(AssessmentBindingModel model)
        {
            using var context = new CandidateReviewDatabase();

            var newAssessment = Assessment.Create(context, model);
            if (newAssessment == null)
            {
                return null;
            }

            context.Assessments.Add(newAssessment);
            context.SaveChanges();

            return newAssessment.Id;
        }

        public AssessmentViewModel? Update(AssessmentBindingModel model)
        {
            using var context = new CandidateReviewDatabase();
            var assessment = context.Assessments.FirstOrDefault(x => x.Id == model.Id);
            if (assessment == null)
            {
                return null;
            }
            assessment.Update(model);
            context.SaveChanges();
            return assessment.GetViewModel;
        }
    }
}
