using ReAct_PME.Domain;
using ReAct_PME.Infrastructure.Persistence;
using Microsoft.EntityFrameworkCore;


namespace ReAct_PME.Infrastructure
{
    public partial class DT_CONVERSATIONRepository : IDT_CONVERSATIONRepository
    {
		private readonly AppDbContext _context;


		public DT_CONVERSATIONRepository(AppDbContext context)
        {
            _context = context;
        }

        private async Task<List<DT_CONVERSATION_LIGNE_DTO>> GetLignes(Guid id)
        {
            var lignes = await new DT_CONVERSATION_LIGNERepository(_context).GetAll_By_ID_CONVERSATION_Async(id);
            return lignes.ToList();
        }

        #region Méthodes privées de Mapping
        private DT_CONVERSATION_DTO MapEntity_DTO(DT_CONVERSATION item)
		{
			DT_CONVERSATION_DTO one = new();
			one.ID_CONVERSATION = item.ID_CONVERSATION;
			one.ID_WORK_FORCE = item.ID_WORK_FORCE;
			one.DATE_START = item.DATE_START;
			one.LIBELLE = item.LIBELLE;
			one.SystemDateCreated = item.SystemDateCreated;
			one.SystemDateUpdated = item.SystemDateUpdated;
			one.IsEnabled = item.IsEnabled;
			one.DT_WORK_FORCE = item.DT_WORK_FORCE;
			one.TypeConv = item.TypeConv;
			one.DT_CONVERSATION_LIGNEs = GetLignes(one.ID_CONVERSATION).Result;
			return one;
		}

		private IEnumerable<DT_CONVERSATION_DTO> MapEntity_DTO(IEnumerable<DT_CONVERSATION> items)
		{
			List<DT_CONVERSATION_DTO> list = new();
			foreach (var item in items)
			{
				DT_CONVERSATION_DTO one = MapEntity_DTO(item);
				list.Add(one);
			}
			return list;
		}

		private DT_CONVERSATION MapDTO_Entity(DT_CONVERSATION_DTO item)
		{
			DT_CONVERSATION one = new();
			one.ID_CONVERSATION = item.ID_CONVERSATION;
			one.ID_WORK_FORCE = item.ID_WORK_FORCE;
			one.DATE_START = item.DATE_START;
			one.LIBELLE = item.LIBELLE;
			one.SystemDateCreated = item.SystemDateCreated;
			one.SystemDateUpdated = item.SystemDateUpdated;
			one.IsEnabled = item.IsEnabled;
			one.DT_WORK_FORCE = item.DT_WORK_FORCE;
            one.TypeConv = item.TypeConv;
            return one;
		}

		private IEnumerable<DT_CONVERSATION> MapDTO_Entity(IEnumerable<DT_CONVERSATION_DTO> items)
		{
			List<DT_CONVERSATION> list = new();
			foreach (var item in items)
			{
				DT_CONVERSATION one = MapDTO_Entity(item);
				list.Add(one);
			}
			return list;
		}


		#endregion
		
		#region CRUD de la table DT_CONVERSATION
		public async Task<bool> Create_Async(DT_CONVERSATION_DTO dt_conversation_dto)
		{
			try
			{
				var item = MapDTO_Entity(dt_conversation_dto);
				if(item.ID_CONVERSATION == Guid.Empty) 
					item.ID_CONVERSATION = Guid.NewGuid(); 

				//Empêche la duplication ou modification involontaire de données liées
				var existingDT_WORK_FORCE_ID_WORK_FORCE = await _context.DT_WORK_FORCE.FindAsync(item.ID_WORK_FORCE);

				if(existingDT_WORK_FORCE_ID_WORK_FORCE != null)
					_context.Entry(existingDT_WORK_FORCE_ID_WORK_FORCE!).State = EntityState.Unchanged;

				item.DT_WORK_FORCE = existingDT_WORK_FORCE_ID_WORK_FORCE!;

				item.SystemDateCreated = DateTime.Now;
				item.SystemDateUpdated = DateTime.Now;

				_context.DT_CONVERSATION.Add(item);
				await _context.SaveChangesAsync();
				return true;
			}
			catch
			{
				return false;
			}
		}

		public async Task<bool> Update_Async(Guid ID_CONVERSATION, DT_CONVERSATION_DTO updatedDT_CONVERSATION)
		{
			var item = _context.DT_CONVERSATION.Find(ID_CONVERSATION);
			if (item == null)
			{
				return false;
			}
			
			//Empêche la duplication ou modification involontaire de données liées
			var existingDT_WORK_FORCE_ID_WORK_FORCE = await _context.DT_WORK_FORCE.FindAsync(item.ID_WORK_FORCE);

			if(existingDT_WORK_FORCE_ID_WORK_FORCE != null)
				_context.Entry(existingDT_WORK_FORCE_ID_WORK_FORCE!).State = EntityState.Unchanged;

			item.DT_WORK_FORCE = existingDT_WORK_FORCE_ID_WORK_FORCE!;

			//Les champs
			item.ID_WORK_FORCE = updatedDT_CONVERSATION.ID_WORK_FORCE;
			item.DATE_START = updatedDT_CONVERSATION.DATE_START;
			item.LIBELLE = updatedDT_CONVERSATION.LIBELLE;
			item.SystemDateCreated = updatedDT_CONVERSATION.SystemDateCreated;
			item.SystemDateUpdated = DateTime.Now;
			item.IsEnabled = updatedDT_CONVERSATION.IsEnabled;
			item.TypeConv = updatedDT_CONVERSATION.TypeConv;

            //using var transaction = await _context.Database.BeginTransactionAsync();

            try
			{
				await _context.SaveChangesAsync();
				//await transaction.CommitAsync();
				return true;
			}
			catch
			{
				//await transaction.RollbackAsync();
				return false;
			}
		}

		public async Task<bool> Delete_Async(Guid ID_CONVERSATION)
		{
			var item = _context.DT_CONVERSATION.Find(ID_CONVERSATION);
			if (item == null)
			{
				return false;
			}
			try
			{
				_context.Attach(item);
				_context.DT_CONVERSATION.Remove(item);
				await _context.SaveChangesAsync();
				return true;
			}
			catch
			{
				return false;
			}
		}

		public async Task<IEnumerable<DT_CONVERSATION_DTO>> GetAll_Async(bool IsActifOnly=false)
		{
			var list = _context.DT_CONVERSATION
				.Include(c => c.DT_WORK_FORCE)
				//.Where(c => IsActifOnly ? c.IsEnabled : true)
			;

			var items = MapEntity_DTO(list.ToList());

			return await Task.FromResult(items.OrderBy(c => c.LIBELLE).ToList());
		}

		public async Task<DT_CONVERSATION_DTO?> GetById_Async(Guid ID_CONVERSATION)
		{
			await Task.Delay(1);
			var itemDTO = _context.DT_CONVERSATION
				.Include(c => c.DT_WORK_FORCE)
				.FirstOrDefaultAsync(c => c.ID_CONVERSATION == ID_CONVERSATION).Result;

			if(itemDTO is null)
			{
				return null;
			}
			else
			{
				var item = MapEntity_DTO(itemDTO);
				return item;
			}
		}

		#endregion

		#region By_ID_WORK_FORCE
		public async Task<IEnumerable<DT_CONVERSATION_DTO>> GetAll_By_ID_WORK_FORCE_Async(Guid ID_WORK_FORCE)
		{
			var list = _context.DT_CONVERSATION
				.Include(c => c.DT_WORK_FORCE)
				.Where(c => c.ID_WORK_FORCE == ID_WORK_FORCE);

			var items = MapEntity_DTO(list.ToList());

			return await Task.FromResult(items.OrderBy(c => c.LIBELLE).ToList());
		}

		public async Task<int> GetCount_By_ID_WORK_FORCE_Async(Guid ID_WORK_FORCE)
		{
			var items = _context.DT_CONVERSATION
				.Where(c => c.ID_WORK_FORCE == ID_WORK_FORCE);

			return await Task.FromResult(items.Count());
		}

		public async Task<bool> Delete_By_ID_WORK_FORCE_Async(Guid ID_WORK_FORCE)
		{
			var items = await GetAll_By_ID_WORK_FORCE_Async(ID_WORK_FORCE);
			if(items == null)
			{
				return false;
			}
			try
			{
				_context.DT_CONVERSATION.RemoveRange(items);
				await _context.SaveChangesAsync();
				return true;
			}
			catch
			{
				return false;
			}
		}

		#endregion



    }
}
