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 ListadoDistribucionGeneralDocument : IDocument
    {
        public ListadoDistribucionGeneralViewModel Model { get; }

        public ListadoDistribucionGeneralDocument(ListadoDistribucionGeneralViewModel 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 General Mensual").SemiBold().FontSize(14);
                column.Item().AlignCenter().Text(Model.NombrePublicacion).FontSize(12);

                column.Item().PaddingTop(1, 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("Mes Consultado: ").SemiBold(); text.Span(Model.MesConsultado); });
                });
            });
        }
        
        void ComposeContent(IContainer container)
        {
            container.PaddingTop(1, Unit.Millimetre).Column(column =>
            {
                column.Spacing(20);

                if (Model.ResumenMensual.Any())
                {
                    column.Item().Element(ComposeResumenTable);
                }
                if (Model.PromediosPorDia.Any())
                {
                    column.Item().Element(ComposePromediosTable);
                }
            });
        }

        void ComposeResumenTable(IContainer container)
        {
            container.Table(table =>
            {
                table.ColumnsDefinition(columns =>
                {
                    columns.ConstantColumn(60);
                    columns.RelativeColumn();
                    columns.RelativeColumn();
                    columns.RelativeColumn();
                    columns.RelativeColumn();
                    columns.RelativeColumn();
                    columns.RelativeColumn();
                });

                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("Tirada");
                    header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Sin Cargo");
                    header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Perdidos");
                    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("Vendidos");
                });

                var dayAbbreviations = new Dictionary<System.DayOfWeek, string>
                {
                    { System.DayOfWeek.Sunday, "Dom" },
                    { System.DayOfWeek.Monday, "Lun" },
                    { System.DayOfWeek.Tuesday, "Mar" },
                    { System.DayOfWeek.Wednesday, "Mie" },
                    { System.DayOfWeek.Thursday, "Jue" },
                    { System.DayOfWeek.Friday, "Vie" },
                    { System.DayOfWeek.Saturday, "Sab" }
                };

                foreach (var item in Model.ResumenMensual.OrderBy(x => x.Fecha))
                {
                    table.Cell().Border(1).Padding(3).Text($"{dayAbbreviations[item.Fecha.DayOfWeek]} {item.Fecha.Day}");
                    table.Cell().Border(1).Padding(3).AlignRight().Text(item.CantidadTirada.ToString("N0"));
                    table.Cell().Border(1).Padding(3).AlignRight().Text(item.SinCargo.ToString("N0"));
                    table.Cell().Border(1).Padding(3).AlignRight().Text(item.Perdidos.ToString("N0"));
                    table.Cell().Border(1).Padding(3).AlignRight().Text(item.Llevados.ToString("N0"));
                    table.Cell().Border(1).Padding(3).AlignRight().Text(item.Devueltos.ToString("N0"));
                    table.Cell().Border(1).Padding(3).AlignRight().Text(item.Vendidos.ToString("N0"));
                }
                
                table.Cell().Border(1).Padding(3);
                table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(Model.ResumenMensual.Sum(x => x.CantidadTirada).ToString("N0")).SemiBold());
                table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(Model.ResumenMensual.Sum(x => x.SinCargo).ToString("N0")).SemiBold());
                table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(Model.ResumenMensual.Sum(x => x.Perdidos).ToString("N0")).SemiBold());
                table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(Model.ResumenMensual.Sum(x => x.Llevados).ToString("N0")).SemiBold());
                table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(Model.ResumenMensual.Sum(x => x.Devueltos).ToString("N0")).SemiBold());
                table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(Model.ResumenMensual.Sum(x => x.Vendidos).ToString("N0")).SemiBold());
            });
        }

        void ComposePromediosTable(IContainer container)
        {
            container.Column(column =>
            {
                // --- TÍTULO DE LA TABLA DE PROMEDIOS ---
                column.Item().PaddingBottom(5).AlignCenter().Text("Promedios Diarios de Distribución").SemiBold();

                column.Item().Table(table =>
                {
                    table.ColumnsDefinition(columns =>
                    {
                        columns.RelativeColumn(1.2f);
                        columns.RelativeColumn();
                        columns.RelativeColumn();
                        columns.RelativeColumn();
                        columns.RelativeColumn();
                        columns.RelativeColumn();
                        columns.RelativeColumn();
                        columns.RelativeColumn();
                    });
                
                    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("Tirada");
                        header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Sin Cargo");
                        header.Cell().Border(1).Background(Colors.Grey.Lighten3).Padding(4).AlignRight().Text("Perdidos");
                        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("Vendidos");
                    });

                    var dayOrder = new Dictionary<string, int> { { "Lunes", 1 }, { "Martes", 2 }, { "Miércoles", 3 }, { "Jueves", 4 }, { "Viernes", 5 }, { "Sábado", 6 }, { "Domingo", 7 } };

                    // Mostramos los promedios por día de la semana
                    foreach (var item in Model.PromediosPorDia.OrderBy(d => dayOrder.GetValueOrDefault(d.Dia, 99)))
                    {
                        table.Cell().Border(1).Padding(3).Text(item.Dia);
                        table.Cell().Border(1).Padding(3).AlignRight().Text(item.CantidadDias.ToString("N0"));
                        table.Cell().Border(1).Padding(3).AlignRight().Text(item.PromedioTirada.ToString("N0"));
                        table.Cell().Border(1).Padding(3).AlignRight().Text(item.PromedioSinCargo.ToString("N0"));
                        table.Cell().Border(1).Padding(3).AlignRight().Text(item.PromedioPerdidos.ToString("N0"));
                        table.Cell().Border(1).Padding(3).AlignRight().Text(item.PromedioLlevados.ToString("N0"));
                        table.Cell().Border(1).Padding(3).AlignRight().Text(item.PromedioDevueltos.ToString("N0"));
                        table.Cell().Border(1).Padding(3).AlignRight().Text(item.PromedioVendidos.ToString("N0"));
                    }
                    
                    // --- FILA GENERAL CON DATOS CALCULADOS DEL VIEWMODEL ---
                    var general = Model.PromedioGeneral;
                    if (general != null)
                    {
                        var boldStyle = TextStyle.Default.SemiBold();
                        table.Cell().Border(1).Padding(3).Text(text => text.Span(general.Dia).Style(boldStyle));
                        table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span(general.CantidadDias.ToString("N0")).Style(boldStyle));
                        table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span(general.PromedioTirada.ToString("N0")).Style(boldStyle));
                        table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span(general.PromedioSinCargo.ToString("N0")).Style(boldStyle));
                        table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span(general.PromedioPerdidos.ToString("N0")).Style(boldStyle));
                        table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span(general.PromedioLlevados.ToString("N0")).Style(boldStyle));
                        table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span(general.PromedioDevueltos.ToString("N0")).Style(boldStyle));
                        table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span(general.PromedioVendidos.ToString("N0")).Style(boldStyle));
                    }
                });
            });
        }
    }
}