using GestionIntegral.Api.Data.Repositories.Radios;
using GestionIntegral.Api.Dtos.Radios;
using GestionIntegral.Api.Models.Radios; // Para Cancion
using Microsoft.Extensions.Logging;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Threading.Tasks;

namespace GestionIntegral.Api.Services.Radios
{
    public class RadioListaService : IRadioListaService
    {
        private readonly ICancionRepository _cancionRepository;
        // private readonly IRitmoRepository _ritmoRepository; // No se usa en la nueva lógica de generación de Excel
        private readonly ILogger<RadioListaService> _logger;

        public RadioListaService(
            ICancionRepository cancionRepository,
            // IRitmoRepository ritmoRepository, // Puede ser removido si no se usa en otro lado
            ILogger<RadioListaService> logger)
        {
            _cancionRepository = cancionRepository;
            // _ritmoRepository = ritmoRepository;
            _logger = logger;
        }

        public async Task<(byte[] FileContents, string ContentType, string FileName, string? Error)> GenerarListaRadioAsync(GenerarListaRadioRequestDto request)
        {
            try
            {
                _logger.LogInformation("Iniciando generación de lista de radio para Mes: {Mes}, Año: {Anio}, Institución: {Institucion}, Radio: {Radio}",
                                       request.Mes, request.Anio, request.Institucion, request.Radio);

                var programacionParaExcel = new List<ProgramacionHorariaExcelDto>();
                int diasEnMes = DateTime.DaysInMonth(request.Anio, request.Mes);

                for (int dia = 1; dia <= diasEnMes; dia++)
                {
                    int horaInicio = (request.Radio == "FM 99.1") ? 0 : 9;
                    int horaFin = 23;

                    for (int hora = horaInicio; hora <= horaFin; hora++)
                    {
                        int cantidadRegistros;
                        if (request.Radio == "FM 99.1")
                        {
                            cantidadRegistros = (hora == 23 || hora == 7 || hora == 15) ? 1 : 5;
                        }
                        else // FM 100.3
                        {
                            cantidadRegistros = (hora == 23 || hora == 15) ? 1 : 2;
                        }

                        if (cantidadRegistros > 0)
                        {
                            var cancionesSeleccionadas = await _cancionRepository.GetRandomCancionesAsync(cantidadRegistros);
                            foreach (var cancion in cancionesSeleccionadas)
                            {
                                programacionParaExcel.Add(new ProgramacionHorariaExcelDto
                                {
                                    Dia = dia,
                                    Hora = hora,
                                    TituloObra = cancion.Tema,
                                    CompositorAutor = cancion.CompositorAutor,
                                    Interprete = cancion.Interprete,
                                    Sello = cancion.Sello,
                                    Album = cancion.Album
                                });
                            }
                        }
                    }
                }

                if (!programacionParaExcel.Any())
                {
                    _logger.LogWarning("No se generaron datos para la lista de radio con los criterios: {@Request}", request);
                    return (Array.Empty<byte>(), "", "", "No se generaron datos para la lista con los criterios dados.");
                }

                string mesText = request.Mes.ToString("00");
                string anioFullText = request.Anio.ToString();
                string anioShortText = anioFullText.Length > 2 ? anioFullText.Substring(anioFullText.Length - 2) : anioFullText;

                byte[] excelBytes = GenerarExcel(programacionParaExcel, request.Institucion, request.Radio, mesText, anioFullText, anioShortText);

                string baseFileName;
                if (request.Institucion == "AADI")
                {
                    baseFileName = request.Radio == "FM 99.1" ? $"AADI-FM99.1-FM-{mesText}{anioShortText}" : $"AADI-FM100.3-FM-{mesText}{anioShortText}";
                }
                else // SADAIC
                {
                    baseFileName = request.Radio == "FM 99.1" ? $"FM99.1-FM-{mesText}{anioShortText}" : $"FM100.3-FM-{mesText}{anioShortText}";
                }
                string excelFileNameInZip = $"{baseFileName}.xlsx";
                string zipFileName = $"{baseFileName}.xlsx.zip"; // Para replicar nombre original del zip

                using (var memoryStream = new MemoryStream())
                {
                    using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
                    {
                        var excelEntry = archive.CreateEntry(excelFileNameInZip, CompressionLevel.Optimal);
                        using (var entryStream = excelEntry.Open())
                        {
                            await entryStream.WriteAsync(excelBytes, 0, excelBytes.Length);
                        }
                    }
                    _logger.LogInformation("Lista de radio generada y empaquetada en ZIP exitosamente: {ZipFileName}", zipFileName);
                    return (memoryStream.ToArray(), "application/zip", zipFileName, null);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error al generar la lista de radio para Mes: {Mes}, Año: {Anio}, Institucion: {Institucion}, Radio: {Radio}", request.Mes, request.Anio, request.Institucion, request.Radio);
                return (Array.Empty<byte>(), "", "", $"Error interno al generar la lista: {ex.Message}");
            }
        }

        private byte[] GenerarExcel(List<ProgramacionHorariaExcelDto> programacion, string institucion, string radio, string mesText, string anioFullText, string anioShortText)
        {
            IWorkbook workbook = new XSSFWorkbook();

            var coreProps = ((XSSFWorkbook)workbook).GetProperties().CoreProperties;
            coreProps.Creator = "GestionIntegral"; // Puedes cambiarlo
            coreProps.Title = $"Reporte {institucion} - {radio} - {mesText}/{anioFullText}";
            // coreProps.Description = "Descripción del reporte"; // Opcional
            // var extendedProps = ((XSSFWorkbook)workbook).GetProperties().ExtendedProperties.GetUnderlyingProperties();
            // extendedProps.Application = "GestionIntegral System"; // Opcional
            // extendedProps.AppVersion = "1.0.0"; // Opcional

            string sheetName;
            if (institucion == "AADI")
            {
                sheetName = radio == "FM 99.1" ? $"SA99{mesText}{anioShortText}" : $"SARE{mesText}{anioShortText}";
            }
            else // SADAIC
            {
                sheetName = radio == "FM 99.1" ? $"FM99{mesText}{anioShortText}" : $"FMRE{mesText}{anioShortText}";
            }
            ISheet sheet = workbook.CreateSheet(sheetName);

            int currentRowIdx = 0;
            if (institucion == "AADI")
            {
                sheet.CreateRow(currentRowIdx++).CreateCell(0).SetCellValue(radio == "FM 99.1" ? "Nombre: FM LA 99.1" : "Nombre: FM 100.3 LA REDONDA");
                sheet.CreateRow(currentRowIdx++).CreateCell(0).SetCellValue("Localidad: La Plata");
                sheet.CreateRow(currentRowIdx++).CreateCell(0).SetCellValue("FM");
                sheet.CreateRow(currentRowIdx++).CreateCell(0).SetCellValue(radio == "FM 99.1" ? "Frecuencia: 99.1" : "Frecuencia: 100.3");
                sheet.CreateRow(currentRowIdx++).CreateCell(0).SetCellValue($"Mes: {mesText}/{anioFullText}");
            }

            IRow headerDataRow = sheet.CreateRow(currentRowIdx++);
            headerDataRow.CreateCell(0).SetCellValue("Día");
            headerDataRow.CreateCell(1).SetCellValue("Hora");
            headerDataRow.CreateCell(2).SetCellValue("Título de la Obra");
            headerDataRow.CreateCell(3).SetCellValue("Compositor-Autor");
            headerDataRow.CreateCell(4).SetCellValue("Intérprete");
            headerDataRow.CreateCell(5).SetCellValue("Sello");
            headerDataRow.CreateCell(6).SetCellValue("Álbum");

            IFont font = workbook.CreateFont();
            font.FontHeightInPoints = 10;
            font.FontName = "Arial";
            ICellStyle cellStyle = workbook.CreateCellStyle();
            cellStyle.SetFont(font);

            foreach (var item in programacion)
            {
                IRow dataRow = sheet.CreateRow(currentRowIdx++);
                dataRow.CreateCell(0).SetCellValue(item.Dia);
                dataRow.CreateCell(1).SetCellValue(item.Hora);
                dataRow.CreateCell(2).SetCellValue(item.TituloObra);
                dataRow.CreateCell(3).SetCellValue(item.CompositorAutor);
                dataRow.CreateCell(4).SetCellValue(item.Interprete);
                dataRow.CreateCell(5).SetCellValue(item.Sello);
                dataRow.CreateCell(6).SetCellValue(item.Album);

                for (int i = 0; i < 7; i++)
                {
                    ICell cell = dataRow.GetCell(i) ?? dataRow.CreateCell(i); // Asegurarse que la celda exista
                    cell.CellStyle = cellStyle;
                }
            }

            sheet.SetColumnWidth(0, 4 * 256);
            sheet.SetColumnWidth(1, 5 * 256);
            sheet.SetColumnWidth(2, 25 * 256);
            sheet.SetColumnWidth(3, 14 * 256);
            sheet.SetColumnWidth(4, 11 * 256);
            sheet.SetColumnWidth(5, 11 * 256);
            sheet.SetColumnWidth(6, 30 * 256);

            short rowHeight = 255; // 12.75 puntos
            for (int i = 0; i < currentRowIdx; i++)
            {
                IRow row = sheet.GetRow(i) ?? sheet.CreateRow(i);
                row.Height = rowHeight;

                // Aplicar estilo a todas las celdas de las filas de encabezado también
                if (i < (institucion == "AADI" ? 5 : 0) || i == (institucion == "AADI" ? 5 : 0)) // Filas de cabecera de AADI o la fila de títulos de columnas
                {
                    // Iterar sobre las celdas que realmente existen o deberían existir
                    int lastCellNum = (institucion == "AADI" && i < 5) ? 1 : 7; // Cabecera AADI solo tiene 1 celda, títulos de datos tienen 7
                    for (int j = 0; j < lastCellNum; j++)
                    {
                        ICell cell = row.GetCell(j) ?? row.CreateCell(j);
                        cell.CellStyle = cellStyle;
                    }
                }
            }

            using (var memoryStream = new MemoryStream())
            {
                workbook.Write(memoryStream, true); // El 'true' es para dejar el stream abierto si se necesita
                return memoryStream.ToArray();
            }
        }
    }
}