using GestionIntegral.Api.Dtos.Reportes.ViewModels;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
using System.Collections.Generic;
using System.Linq;

namespace GestionIntegral.Api.Controllers.Reportes.PdfTemplates
{
    public class ListadoDistribucionDistribuidoresDocument : IDocument
    {
        public ListadoDistribucionDistribuidoresViewModel Model { get; }

        public ListadoDistribucionDistribuidoresDocument(ListadoDistribucionDistribuidoresViewModel model)
        {
            Model = model;
        }

        public DocumentMetadata GetMetadata() => DocumentMetadata.Default;

        public void Compose(IDocumentContainer container)
        {
            container.Page(page =>
            {
                page.Margin(1, Unit.Centimetre);
                page.DefaultTextStyle(x => x.FontFamily("Arial").FontSize(10));
                
                page.Header().Element(ComposeHeader);
                page.Content().Element(ComposeContent);
                page.Footer().AlignCenter().Text(x => { x.Span("Página "); x.CurrentPageNumber(); });
            });
        }

        void ComposeHeader(IContainer container)
        {
            container.Column(column =>
            {
                column.Item().AlignCenter().Text("Listado de Distribución").SemiBold().FontSize(14);
                column.Item().AlignCenter().Text(Model.NombreDistribuidor).FontSize(12);
                column.Item().AlignCenter().Text(Model.NombrePublicacion).FontSize(11);

                column.Item().PaddingTop(5, Unit.Millimetre).Row(row =>
                {
                    row.RelativeItem().Text(text => { text.Span("Fecha de Reporte: ").SemiBold(); text.Span(Model.FechaReporte); });
                    row.RelativeItem().AlignRight().Text(text => { text.Span("Periodo: ").SemiBold(); text.Span($"{Model.FechaDesde} - {Model.FechaHasta}"); });
                });
            });
        }
        
        void ComposeContent(IContainer container)
        {
            container.PaddingTop(8, Unit.Millimetre).Column(column =>
            {
                column.Spacing(15);
                column.Item().Text("Distribución").SemiBold().FontSize(12);
                column.Item().Element(ComposeDetalleDiarioTable);
                
                column.Item().PaddingTop(5, Unit.Millimetre);

                column.Item().Text("Promedios").SemiBold().FontSize(12);
                column.Item().Element(ComposePromediosTable);
            });
        }

        void ComposeDetalleDiarioTable(IContainer container)
        {
            container.Table(table =>
            {
                table.ColumnsDefinition(columns =>
                {
                    columns.ConstantColumn(50); columns.RelativeColumn();
                    columns.RelativeColumn(); columns.RelativeColumn();
                    columns.RelativeColumn(2); columns.RelativeColumn(2);
                });
                table.Header(header =>
                {
                    header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).Text("Día");
                    header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Llevados");
                    header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Devueltos");
                    header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Venta Neta");
                    header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Promedio");
                    header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("% Devolución");
                });

                decimal ventaNetaAcumulada = 0;
                int conteoDias = 0;

                foreach (var item in Model.DetalleDiario.OrderBy(x => x.Dia))
                {
                    var llevados = item.Llevados ?? 0;
                    var devueltos = item.Devueltos ?? 0;
                    var ventaNetaDia = llevados - devueltos;
                    if(llevados > 0)
                    {
                        ventaNetaAcumulada += ventaNetaDia;
                        conteoDias++;
                    }
                    var promedio = conteoDias > 0 ? ventaNetaAcumulada / conteoDias : 0;
                    var porcDevolucion = llevados > 0 ? (decimal)devueltos * 100 / llevados : 0;
                    
                    table.Cell().Border(1).Padding(3).Text(item.Dia.ToString());
                    table.Cell().Border(1).Padding(3).AlignRight().Text(llevados.ToString("N0"));
                    table.Cell().Border(1).Padding(3).AlignRight().Text(devueltos.ToString("N0"));
                    table.Cell().Border(1).Padding(3).AlignRight().Text(ventaNetaDia.ToString("N0"));
                    table.Cell().Border(1).Padding(3).AlignRight().Text(promedio.ToString("N0"));
                    table.Cell().Border(1).Padding(3).AlignRight().Text(porcDevolucion.ToString("F2") + "%");
                }
                
                var totalLlevados = Model.DetalleDiario.Sum(i => i.Llevados ?? 0);
                var totalDevueltos = Model.DetalleDiario.Sum(i => i.Devueltos ?? 0);
                var totalVentaNeta = totalLlevados - totalDevueltos;
                var totalPorcDevolucion = totalLlevados > 0 ? (decimal)totalDevueltos * 100 / totalLlevados : 0;
                
                var boldStyle = TextStyle.Default.SemiBold();
                table.Cell().Border(1).Padding(3);
                table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(totalLlevados.ToString("N0")).Style(boldStyle));
                table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(totalDevueltos.ToString("N0")).Style(boldStyle));
                table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(totalVentaNeta.ToString("N0")).Style(boldStyle));
                table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span((ventaNetaAcumulada / (conteoDias > 0 ? conteoDias : 1)).ToString("N0")).Style(boldStyle));
                table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(totalPorcDevolucion.ToString("F2") + "%").Style(boldStyle));
            });
        }
        
        void ComposePromediosTable(IContainer container)
        {
            var dayOrder = new Dictionary<string, int> { { "Lunes", 1 }, { "Martes", 2 }, { "Miércoles", 3 }, { "Jueves", 4 }, { "Viernes", 5 }, { "Sábado", 6 }, { "Domingo", 7 }};
            
            container.Table(table =>
            {
                table.ColumnsDefinition(columns =>
                {
                    columns.RelativeColumn(1.5f); columns.RelativeColumn();
                    columns.RelativeColumn(); columns.RelativeColumn();
                    columns.RelativeColumn(); columns.RelativeColumn(1.2f);
                });
                table.Header(header =>
                {
                    header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).Text("Día");
                    header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Cant. Días");
                    header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Prom. Llevados");
                    header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Prom. Devueltos");
                    header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Prom. Ventas");
                    header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("% Devolución");
                });
                foreach (var item in Model.PromediosPorDia.Where(p => p.Dia != "General").OrderBy(d => dayOrder.GetValueOrDefault(d.Dia, 99)))
                {
                    var llevados = item.Promedio_Llevados ?? 0;
                    var devueltos = item.Promedio_Devueltos ?? 0;
                    var porcDevolucion = llevados > 0 ? (decimal)devueltos * 100 / llevados : 0;
                    
                    table.Cell().Border(1).Padding(3).Text(item.Dia);
                    table.Cell().Border(1).Padding(3).AlignRight().Text(item.Cant?.ToString("N0") ?? "0");
                    table.Cell().Border(1).Padding(3).AlignRight().Text(llevados.ToString("N0"));
                    table.Cell().Border(1).Padding(3).AlignRight().Text(devueltos.ToString("N0"));
                    table.Cell().Border(1).Padding(3).AlignRight().Text(item.Promedio_Ventas?.ToString("N0") ?? "0");
                    table.Cell().Border(1).Padding(3).AlignRight().Text(porcDevolucion.ToString("F2") + "%");
                }

                // --- FILA GENERAL ---
                var general = Model.PromedioGeneral;
                if (general != null)
                {
                    var boldStyle = TextStyle.Default.SemiBold();
                    var llevadosGeneral = general.Llevados ?? 0; // Usamos el total para el %
                    var devueltosGeneral = general.Devueltos ?? 0; // Usamos el total para el %
                    var porcDevolucionGeneral = llevadosGeneral > 0 ? (decimal)devueltosGeneral * 100 / llevadosGeneral : 0;

                    table.Cell().Border(1).Padding(3).Text(t => t.Span(general.Dia).Style(boldStyle));
                    table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(general.Cant?.ToString("N0")).Style(boldStyle));
                    table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(general.Promedio_Llevados?.ToString("N0")).Style(boldStyle));
                    table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(general.Promedio_Devueltos?.ToString("N0")).Style(boldStyle));
                    table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(general.Promedio_Ventas?.ToString("N0")).Style(boldStyle));
                    table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(porcDevolucionGeneral.ToString("F2") + "%").Style(boldStyle));
                }
            });
        }
    }
}