using Entities;
using Microsoft.EntityFrameworkCore;
using StubbedContextLib;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DbContextLib
{
    public class UnitOfWork : IDisposable
    {
        private bool disposed = false;

        private GenericRepository<GroupEntity>? groupRepository;

        private GenericRepository<LangueEntity>? langueRepository;

        private GenericRepository<RoleEntity>? roleRepository;

        private GenericRepository<TranslateEntity>? translateRepository;

        private GenericRepository<UserEntity>? userRepository;

        private GenericRepository<VocabularyEntity>? vocabularyRepository;

        private GenericRepository<VocabularyListEntity>? vocabularyListRepository;




        private SAEContext _context {  get; set; }
        public UnitOfWork(SAEContext context) {
            _context = context;

            _context.Database.EnsureCreated();
        }

        public UnitOfWork(StubbedContext context) 
        {
            _context = context;

            _context.Database.EnsureCreated();
        }

        public UnitOfWork(DbContextOptions<SAEContext> options)
: this(new StubbedContext(options))
        {
        }


        public UnitOfWork()
            : this(new StubbedContext())
        {
        }

        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed && disposing)
            {
                _context.Dispose();
            }
            this.disposed = true;
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        public GenericRepository<GroupEntity> GroupRepository
        {
            get
            {
                if (groupRepository == null)
                {
                    groupRepository = new GenericRepository<GroupEntity>(_context);
                }
                return groupRepository;
            }
        }

        public GenericRepository<LangueEntity> LangueRepository
        {
            get
            {
                if (langueRepository == null)
                {
                    langueRepository = new GenericRepository<LangueEntity>(_context);
                }
                return langueRepository;
            }
        }

        public GenericRepository<RoleEntity> RoleRepository
        {
            get
            {
                if (roleRepository == null)
                {
                    roleRepository = new GenericRepository<RoleEntity>(_context);
                }
                return roleRepository;
            }
        }

        public GenericRepository<TranslateEntity> TranslateRepository
        {
            get
            {
                if (translateRepository == null)
                {
                    translateRepository = new GenericRepository<TranslateEntity>(_context);
                }
                return translateRepository;
            }
        }

        public GenericRepository<UserEntity> UserRepository
        {
            get
            {
                if (userRepository == null)
                {
                    userRepository = new GenericRepository<UserEntity>(_context);
                }
                return userRepository;
            }
        }

        public GenericRepository<VocabularyEntity> VocabularyRepository
        {
            get
            {
                if (vocabularyRepository == null)
                {
                    vocabularyRepository = new GenericRepository<VocabularyEntity>(_context);
                }
                return vocabularyRepository;
            }
        }

        public GenericRepository<VocabularyListEntity> VocabularyListRepository
        {
            get
            {
                if (vocabularyListRepository == null)
                {
                    vocabularyListRepository = new GenericRepository<VocabularyListEntity>(_context);
                }
                return vocabularyListRepository;
            }
        }

        public async Task<int> SaveChangesAsync()
        {
            int result = 0;
            try
            {
                result = await _context.SaveChangesAsync();
            }
            catch
            {
                RejectChanges();
                return -1;
            }
            foreach (var entity in _context.ChangeTracker.Entries()
                .Where(e => e.State != EntityState.Detached))
            {
                entity.State = EntityState.Detached;
            }
            return result;
        }

        public void RejectChanges()
        {
            foreach (var entry in _context.ChangeTracker.Entries()
                .Where(e => e.State != EntityState.Unchanged))
            {
                switch (entry.State)
                {
                    case EntityState.Added:
                        entry.State = EntityState.Detached;
                        break;
                    case EntityState.Modified:
                    case EntityState.Deleted:
                        entry.Reload();
                        break;
                }
            }
        }


    }
}
