using Core.Interfaces;
using Domain.Entities;
using Domain.Generics;
using Domain.SearchParams;
using Models.Interfaces;
using System.Reflection;
using Transversal.Services;

namespace Core.Services
{
    public class PatientService : IPatientDom
    {
        #region Declaraciones y Constructor
        private readonly IPhSPatientRepository _repository;
        public PatientService(IPhSPatientRepository patientRepository)
        {
            _repository = patientRepository ?? throw new ArgumentNullException(nameof(patientRepository));
        }
        #endregion
        #region Métodos de servicio
        public async Task<PagedResult<EPatient>> GetAllAsync(int page = 1, int pageSize = 50)
        {
            try
            {
                return await _repository.GetAllAsync(page, pageSize);
            }
            catch (Exception ex)
            {
                var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod";
                throw new Exception($"{methodName} Message: {ex.Message}", ex);
            }
        }
        public async Task<EPatient?> GetByIdAsync(int id)
        {
            try
            {
                return await _repository.GetByIdAsync(id);
            }
            catch (Exception ex)
            {
                var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod";
                throw new Exception($"{methodName} Message: {ex.Message}", ex);
            }
        }
        public async Task<EPatient> CreateAsync(EPatient entity)
        {
            if (entity is null)
                throw new ArgumentNullException(nameof(entity), "El paciente no puede ser nulo.");

            if (string.IsNullOrWhiteSpace(entity.Firstname) || string.IsNullOrWhiteSpace(entity.Lastname))
                throw new ArgumentException("Debe completar el nombre y apellido del paciente.");

            if (string.IsNullOrWhiteSpace(entity.DocumentNumber))
                throw new ArgumentException("Debe completar el número de documento del paciente.");

            return await _repository.CreateAsync(entity);
        }
        public async Task<bool> UpdateAsync(EPatient entity)
        {
            if (entity is null)
                throw new ArgumentNullException(nameof(entity), "El paciente no puede ser nulo.");

            if (string.IsNullOrWhiteSpace(entity.Firstname) || string.IsNullOrWhiteSpace(entity.Lastname))
                throw new ArgumentException("Debe completar el nombre y apellido del paciente.");

            if (string.IsNullOrWhiteSpace(entity.DocumentNumber))
                throw new ArgumentException("Debe completar el número de documento del paciente.");

            return await _repository.UpdateAsync(entity);
        }
        public async Task<PagedResult<EPatient>> SearchAsync(string? name, string? document, int page = 1, int pageSize = 50)
        {
            try
            {
                return await _repository.SearchAsync(name, document, page, pageSize);
            }
            catch (Exception ex)
            {
                var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod";
                throw new Exception($"{methodName} Message: {ex.Message}", ex);
            }
        }
        public Task<bool> DeleteAsync(int id)
        {
            // Implementar según políticas del sistema (soft delete, etc.)
            throw new NotImplementedException();
        }
        public async Task<byte[]> ExportFilteredPatientsToExcelAsync(PatientSearchParams searchParams)
        {
            try
            {
                var searchResult = await SearchAsync(
                    searchParams.Name,
                    searchParams.Document,
                    searchParams.Page,
                    searchParams.PageSize
                );

                if (searchResult?.Items is null || !searchResult.Items.Any())
                {
                    throw new Exception("No se encontraron pacientes para exportar.");
                }

                var stream = new XLSXExportBase();

                var patientData = searchResult.Items.Select(p => new
                {
                    p.Id,
                    p.Firstname,
                    p.Lastname,
                    p.DocumentNumber,
                    p.AffiliateNumber,
                    p.Email,
                    p.Phone,
                    p.Birthdate,
                    p.Gender
                }).ToList();

                var excelFile = stream.ExportExcel(patientData);
                return excelFile;
            }
            catch (Exception ex)
            {
                var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod";
                throw new Exception($"{methodName} - Error al exportar pacientes: {ex.Message}", ex);
            }
        }
        #endregion
    }
}