using Microsoft.EntityFrameworkCore;
using PolyclinicContracts.BindingModels;
using PolyclinicContracts.SearchModels;
using PolyclinicContracts.StoragesContracts;
using PolyclinicContracts.ViewModels;
using PolyclinicDatabaseImplement.Models;
using SecuritySystemDatabaseImplement;

namespace PolyclinicDatabaseImplement.Implements
{
    public class RecipeStorage : IRecipeStorage
    {
        public List<RecipeViewModel> GetFullList()
        {
            using var database = new PolyclinicDatabase();
            return database.Recipes
                .Include(x => x.Course)
                .Include(x => x.Procedures)
                .ThenInclude(x => x.Procedure)
                .Select(x => x.GetViewModel)
                .ToList();
        }
        public List<RecipeViewModel> GetFilteredList(RecipeSearchModel bindingModel)
        {
            if (!bindingModel.Id.HasValue || string.IsNullOrEmpty(bindingModel.Comment))
            {
                return new();
            }
            using var database = new PolyclinicDatabase();
            return database.Recipes
                .Include(x => x.Procedures)
                .ThenInclude(x => x.Procedure)
                .Where(x => x.Comment.Contains(bindingModel.Comment))
                .Select(x => x.GetViewModel)
                .ToList();
        }

        public RecipeViewModel? GetElement(RecipeSearchModel bindingModel)
        {
            if (!bindingModel.Id.HasValue)
            {
                return null;
            }
            using var database = new PolyclinicDatabase();
            return database.Recipes
                .Include(x => x.Procedures)
                .ThenInclude(x => x.Procedure)
                .FirstOrDefault(x => (!string.IsNullOrEmpty(bindingModel.Comment) &&
                x.Comment == bindingModel.Comment) || 
                (bindingModel.Id.HasValue && x.Id == bindingModel.Id))?
                .GetViewModel;
        }

        public RecipeViewModel? Insert(RecipeBindingModel bindingModel)
        {
            using var database = new PolyclinicDatabase();
            var newRecipe = Recipe.Create(database, bindingModel);
            if (newRecipe == null)
            {
                return null;
            }
            database.Recipes.Add(newRecipe);
            database.SaveChanges();
            return newRecipe.GetViewModel;
        }

        public RecipeViewModel? Update(RecipeBindingModel bindingModel)
        {
            using var database = new PolyclinicDatabase();
            using var transaction = database.Database.BeginTransaction();
            try
            {
                var Recipe = database.Recipes.FirstOrDefault(rec => rec.Id == bindingModel.Id);
                if (Recipe == null)
                {
                    return null;
                }
                Recipe.Update(bindingModel);
                database.SaveChanges();
                Recipe.UpdateProcedures(database, bindingModel);
                transaction.Commit();
                return Recipe.GetViewModel;
            }
            catch
            {
                transaction.Rollback();
                throw;
            }
        }

        public RecipeViewModel? Delete(RecipeBindingModel bindingModel)
        {
            using var database = new PolyclinicDatabase();
            var recipe = database.Recipes
                .Include(x => x.Procedures)
                .FirstOrDefault(x => x.Id == bindingModel.Id);
            if (recipe == null)
            {
                return null;
            }
            database.Recipes.Remove(recipe);
            database.SaveChanges();
            return recipe.GetViewModel;
        }
    }
}