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

namespace Core.Services
{
    public class ProfessionalService : IProfessionalDom
    {
        #region Declaraciones y Constructor
        private readonly IPhSProfessionalRepository _repository;

        public ProfessionalService(IPhSProfessionalRepository professionalRepository)
        {
            _repository = professionalRepository ?? throw new ArgumentNullException(nameof(professionalRepository));
        }
        #endregion
        #region Métodos
        public async Task<PagedResult<EProfessional>> GetAllAsync(int page = 1, int pageSize = 50)
        {
            try
            {
                return await _repository.GetAllAsync(page, pageSize);
            }
            catch (Exception ex)
            {
                var method = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod";
                throw new Exception($"{method} Message: {ex.Message}", ex);
            }
        }
        public async Task<EProfessional?> GetByIdAsync(int id)
        {
            try
            {
                return await _repository.GetByIdAsync(id);
            }
            catch (Exception ex)
            {
                var method = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod";
                throw new Exception($"{method} Message: {ex.Message}", ex);
            }
        }
        public async Task<EProfessional> CreateAsync(EProfessional entity)
        {
            if (entity is null)
                throw new ArgumentNullException(nameof(entity), "El profesional no puede ser nulo.");

            if (string.IsNullOrWhiteSpace(entity.Fullname))
                throw new ArgumentException("Debe ingresar el nombre completo del profesional.", nameof(entity.Fullname));

            if (string.IsNullOrWhiteSpace(entity.DocumentNumber))
                throw new ArgumentException("Debe ingresar un número de documento.", nameof(entity.DocumentNumber));

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

            if (string.IsNullOrWhiteSpace(entity.Fullname))
                throw new ArgumentException("Debe ingresar el nombre completo del profesional.", nameof(entity.Fullname));

            if (string.IsNullOrWhiteSpace(entity.DocumentNumber))
                throw new ArgumentException("Debe ingresar un número de documento o matricula.", nameof(entity.DocumentNumber));

            return await _repository.UpdateAsync(entity);
        }
        public async Task<PagedResult<EProfessional>> SearchAsync(
            string? fullname, string? document, string? type,
            int page = 1, int pageSize = 50)
        {
            try
            {
                return await _repository.SearchAsync(fullname, document, type, page, pageSize);
            }
            catch (Exception ex)
            {
                var method = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod";
                throw new Exception($"{method} Message: {ex.Message}", ex);
            }
        }
        public async Task<byte[]> ExportFilteredProfessionalsToExcelAsync(ProfessionalSearchParams searchParams)
        {
            try
            {
                // Realiza la búsqueda de clientes con los parámetros proporcionados
                var searchResult = await SearchAsync(
                    searchParams.Fullname,
                    searchParams.Document,
                    searchParams.Type,
                    searchParams.Page,
                    searchParams.PageSize
                );

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

                var stream = new XLSXExportBase();
                var professionalsData = searchResult.Items.Select(p => new
                {
                    p.Id,
                    p.Fullname,
                    p.DocumenttypeName,
                    p.DocumentNumber,
                    Tipo = p.Type,
                    Especialidad = p.Specialty?.Name,
                    p.Email,
                    Teléfono1 = p.Phone1,
                    Teléfono2 = p.Phone2,
                    Dirección = p.Address,
                    Ciudad = p.City,
                    Provincia = p.Province,
                    CódigoPostal = p.Postalcode,
                    Matrícula = p.License,
                    p.Active,
                    FechaAlta = p.Createdat.ToString("dd/MM/yyyy")
                }).ToList();


                return stream.ExportExcel(professionalsData);
            }
            catch (Exception ex)
            {
                var method = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod";
                throw new Exception($"{method} Message: {ex.Message}", ex);
            }
        }
        public async Task<bool> DeleteAsync(int id)
        {
            try
            {
                return await _repository.DeleteAsync(id);
            }
            catch (Exception ex)
            {
                var method = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod";
                throw new Exception($"{method} Message: {ex.Message}", ex);
            }
        }
        #endregion
    }
}
