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


namespace Core.Services
{
    public class ProductService : IProductDom
    {
        #region Declaraciones y Constructor
        private readonly IPhSProductRepository _repository;
        public ProductService(IPhSProductRepository repository)
        {
            _repository = repository ?? throw new ArgumentNullException(nameof(repository));
        }
        #endregion

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

            if (string.IsNullOrWhiteSpace(entity.Name))
                throw new ArgumentException("El producto debe tener un nombre válido.");

            if (entity.Baseprice < 0)
                throw new ArgumentException("El precio base no puede ser negativo.");

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

            if (string.IsNullOrWhiteSpace(entity.Name))
                throw new ArgumentException("El producto debe tener un nombre válido.");

            if (entity.Baseprice < 0)
                throw new ArgumentException("El precio base no puede ser negativo.");

            return await _repository.UpdateAsync(entity);
        }
        public async Task<bool> DeleteAsync(int id)
        {
            return await _repository.DeleteAsync(id);
        }
        public async Task<byte[]> ExportFilteredProductsToExcelAsync(ProductSearchParams searchParams)
        {
            try
            {
                // Realiza la búsqueda de productos con los parámetros proporcionados
                var searchResult = await SearchAsync(searchParams.Term, searchParams.Page, searchParams.PageSize);
                if (searchResult?.Items is null || !searchResult.Items.Any())
                {
                    throw new Exception("No se encontraron productos para exportar.");
                }
                // Llamamos a un método que exporta los datos a Excel
                var stream = new XLSXExportBase();
                // Convertimos los resultados de la búsqueda a un formato adecuado para el exportador
                var productData = searchResult.Items.Select(p => new
                {
                    p.Id,
                    p.Name,
                    p.Description,
                    BusinessUnit = p.Businessunits?.Code,
                    Category = p.Category?.Name,
                    p.Origin,
                    p.Baseprice,
                    p.Currency,
                    p.Isactive
                }).ToList();
                // Genera el archivo Excel
                var excelFile = stream.ExportExcel(productData);
                // Devuelve el archivo Excel como un array de bytes
                return excelFile;
            }
            catch (Exception ex)
            {
                var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod";
                throw new Exception($"{methodName} Message: {ex.Message}", ex);
            }
        }
        #endregion
    }
}
