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

namespace Core.Services
{
    public class LSProductService : ILSProductDom
    {
        private readonly IPhLSMProductRepository _repository;
        private readonly IPhLSMProductDivisionRepository _divisionRepo;
        private readonly IPhLSMUnitOfMeasureRepository _unitRepo;

        private List<string> _divisionCodes = [];
        private List<string> _unitCodes = [];

        public LSProductService(
            IPhLSMProductRepository repository,
            IPhLSMProductDivisionRepository divisionRepo ,
            IPhLSMUnitOfMeasureRepository unitRepo)
        {
            _repository = repository ?? throw new ArgumentNullException(nameof(repository));
            _divisionRepo = divisionRepo ?? throw new ArgumentNullException(nameof(divisionRepo));
            _unitRepo = unitRepo ?? throw new ArgumentNullException(nameof(unitRepo));
        }

        public async Task<PagedResult<ELSProduct>> SearchAsync(LSProductSearchParams searchParams)
        {
            return await _repository.SearchAsync(searchParams);
        }

        public async Task<ELSProduct?> GetByIdAsync(int id)
        {
            return await _repository.GetByIdAsync(id);
        }

        public async Task<ELSProduct> CreateAsync(ELSProduct entity)
        {
            return await _repository.CreateAsync(entity);
        }

        public async Task<bool> UpdateAsync(ELSProduct entity)
        {
            return await _repository.UpdateAsync(entity);
        }

        public async Task<bool> DeleteAsync(int id)
        {
            return await _repository.DeleteAsync(id);
        }

        public async Task<byte[]> ExportToExcelAsync(LSProductSearchParams searchParams)
        {
            try
            {
                var result = await _repository.SearchAsync(searchParams);
                if (result?.Items == null || !result.Items.Any())
                    throw new Exception("No se encontraron productos para exportar.");

                var exportador = new XLSXExportBase();

                var exportData = result.Items.Select(p => new
                {
                    p.Id,
                    p.FactoryCode,
                    p.ExternalCode,
                    p.RegulatoryCode,
                    p.Name,
                    p.Descripcion,
                    Tipo = p.ProductType == 1 ? "Implantable" :
                           p.ProductType == 2 ? "Instrumental" :
                           p.ProductType == 3 ? "Inyectable" : "Otro",
                    Trazabilidad = p.TraceabilityType == 1 ? "No aplica" :
                                   p.TraceabilityType == 2 ? "Por cantidad" :
                                   p.TraceabilityType == 3 ? "Por lote y vencimiento" : "Otro",
                    PlusProcess = p.PlusProcess ? "Sí" : "No",
                    División = p.Division?.Name ?? "-",
                    Unidad = p.Unit?.Name ?? "-"
                }).ToList();

                return exportador.ExportExcel(exportData);
            }
            catch (Exception ex)
            {
                var method = MethodBase.GetCurrentMethod()?.Name ?? "ExportToExcel";
                throw new Exception($"Error en {method}: {ex.Message}", ex);
            }
        }
        public byte[] GetImportTemplate()
        {
            var path = Path.Combine(Directory.GetCurrentDirectory(), "Resources", "Templates", "Stock", "plantilla_productos.xlsx");

            if (!File.Exists(path))
                throw new FileNotFoundException("No se encontró la plantilla de importación de productos.", path);

            return File.ReadAllBytes(path);
        }
        public List<ProductImportPreviewDto> PreviewImportFromExcel(byte[] fileBytes)
        {
            var importador = new XLSXImportBase();
            LoadReferenceCodes(); // Cargar códigos de referencia antes de procesar el archivo
            var rawItems = importador.ReadProductImport(fileBytes);
            foreach (var item in rawItems)
            {
                // Validaciones de dominio
                if (!_divisionCodes.Contains(item.DivisionCode))
                    item.ErrorMessage = "División no reconocida";
                else if (!_unitCodes.Contains(item.UnitCode))
                    item.ErrorMessage = "Unidad no reconocida";
                else if (item.ProductType < 1 || item.ProductType > 3)
                    item.ErrorMessage = "Tipo de producto inválido";
                // Agregar validaciones extras...
            }

            return rawItems;
        }
        private void LoadReferenceCodes()
        {
            _divisionCodes = _divisionRepo.GetAllAsync().Result.Items.Select(x => x.Code).ToList();
            _unitCodes = _unitRepo.GetAllAsync().Result.Items.Select(x => x.Code).ToList();
        }
        public async Task<ProductImportResultDto> ImportProductsAsync(List<ProductImportPreviewDto> items)
        {
            if (items == null || !items.Any())
                return new ProductImportResultDto { Inserted = 0, Skipped = 0 };

            try
            {
                return await _repository.ImportProductsAsync(items);
            }
            catch (Exception ex)
            {
                var method = MethodBase.GetCurrentMethod()?.Name ?? "ImportProductsAsync";
                throw new Exception($"Error en {method}: {ex.Message}", ex);
            }
        }
    }
}
