using Microsoft.EntityFrameworkCore;
using Models.Interfaces;
using Domain.Entities;
using Models.Helpers;
using Models.Models;
using Domain.Generics;

namespace Models.Repositories
{
    public class PhSInstitutionRepository(PhronCareOperationsHubContext context):IPhSInstitutionRepository
    {
        #region Declaraciones y Constructor
        private readonly PhronCareOperationsHubContext _context = context;
        #endregion
        #region Metodos de clase
        public async Task<PagedResult<EInstitution>> GetAllAsync(int page = 1, int pageSize = 50)
        {
            var query = _context.PhSInstitutions.AsNoTracking().OrderBy(x => x.Name);
            var totalItems = await query.CountAsync();

            var pagedEntities = await query.ToPagedResultAsync(page, pageSize);

            return new PagedResult<EInstitution>
            {
                Items = pagedEntities.Items.Select(EntityMapper.MapEntity<PhSInstitution, EInstitution>),
                TotalItems = pagedEntities.TotalItems,
                Page = pagedEntities.Page,
                PageSize = pagedEntities.PageSize
            };
        }
        public async Task<EInstitution?> GetByIdAsync(int id)
        {
            var entity = await _context.PhSInstitutions.AsNoTracking().FirstOrDefaultAsync(x => x.Id == id);
            return entity == null ? null : EntityMapper.MapEntity<PhSInstitution, EInstitution>(entity);
        }
        public async Task<PagedResult<EInstitution>> SearchAsync(string? name, string? type, string? province, int page = 1, int pageSize = 50)
    {
        var query = _context.PhSInstitutions.AsQueryable();

        if (!string.IsNullOrWhiteSpace(name))
        {
            var lowered = name.ToLower();
            query = query.Where(i => i.Name.ToLower().Contains(lowered));
        }

        if (!string.IsNullOrWhiteSpace(type))
        {
            var lowered = type.ToLower();
            query = query.Where(i => i.Type != null && i.Type.ToLower().Contains(lowered));
        }

        if (!string.IsNullOrWhiteSpace(province))
        {
            var lowered = province.ToLower();
            query = query.Where(i => i.Province != null && i.Province.ToLower().Contains(lowered));
        }

        var pagedEntities = await query.ToPagedResultAsync(page, pageSize);

        return new PagedResult<EInstitution>
        {
            Items = pagedEntities.Items.Select(EntityMapper.MapEntity<PhSInstitution, EInstitution>),
            TotalItems = pagedEntities.TotalItems,
            Page = pagedEntities.Page,
            PageSize = pagedEntities.PageSize
        };
    }
        public async Task<EInstitution> CreateAsync(EInstitution model)
        {
            if (model == null)
                throw new ArgumentNullException(nameof(model), "La insitucion no puede ser nula.");
            try
            {
                var entity = EntityMapper.MapEntity<EInstitution, PhSInstitution>(model);
                    _context.PhSInstitutions.Add(entity);
                await _context.SaveChangesAsync();
                return EntityMapper.MapEntity<PhSInstitution, EInstitution>(entity);
            }
            catch (DbUpdateException dbEx)
            {
                throw new Exception("Error al guardar la institucion en la base de datos.", dbEx);
            }
            catch (Exception ex)
            {
                throw new Exception("Error inesperado al crear la institucion: " + ex.Message, ex);
            }
        }
        public async Task<bool> UpdateAsync(EInstitution model)
        {
            if (model == null)
                throw new ArgumentNullException(nameof(model));

            try
            {
                var existingInstitution = await _context.PhSInstitutions.FirstOrDefaultAsync(x => x.Id == model.Id);
                if (existingInstitution == null)
                    return false;

                EntityMapper.MapEntityToExisting(model, existingInstitution); // Actualiza campos
                await _context.SaveChangesAsync();
                return true;
            }
            catch (Exception)
            {
                return false;
            }

        }
        #endregion
    }
}
