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

    public ListadoDistribucionCanillasDocument(ListadoDistribucionCanillasViewModel 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 - Canillitas").SemiBold().FontSize(14);
        column.Item().AlignCenter().Text(Model.NombrePublicacion).FontSize(12);

        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); // Día
                columns.RelativeColumn();   // Llevados
                columns.RelativeColumn();   // Devueltos
                columns.RelativeColumn();   // Venta Neta
                columns.RelativeColumn(2);  // Promedio (columna vacía en el original)
                columns.RelativeColumn(2);  // % Devolución
              });

        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 ventaNetaDia = item.Llevados - item.Devueltos;
          ventaNetaAcumulada += ventaNetaDia;
          conteoDias++;
          var promedio = ventaNetaAcumulada / conteoDias;
          var porcDevolucion = item.Llevados > 0 ? (decimal)item.Devueltos * 100 / item.Llevados : 0;

          table.Cell().Border(1).Padding(3).Text(item.Dia.ToString());
          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(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 totalVentaNeta = Model.TotalesDetalleDiario.Llevados - Model.TotalesDetalleDiario.Devueltos;
        var totalPorcDevolucion = Model.TotalesDetalleDiario.Llevados > 0 ? (decimal)Model.TotalesDetalleDiario.Devueltos * 100 / Model.TotalesDetalleDiario.Llevados : 0;

        table.Cell().Border(1).Padding(3); // Celda vacía
        table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(Model.TotalesDetalleDiario.Llevados.ToString("N0")).SemiBold());
        table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(Model.TotalesDetalleDiario.Devueltos.ToString("N0")).SemiBold());
        table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(totalVentaNeta.ToString("N0")).SemiBold());
        table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span((ventaNetaAcumulada / (conteoDias > 0 ? conteoDias : 1)).ToString("N0")).SemiBold());
        table.Cell().Border(1).Padding(3).AlignRight().Text(t => t.Span(totalPorcDevolucion.ToString("F2")).SemiBold());
      });
    }

    void ComposePromediosTable(IContainer container)
    {
      container.Column(column =>
      {
        column.Item().PaddingBottom(5).Text("Promedios por Día de Semana").SemiBold().FontSize(11);
        column.Item().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 Semana");
        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");
      });

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

        foreach (var item in Model.PromediosPorDia.OrderBy(d => dayOrder.GetValueOrDefault(d.Dia, 99)))
        {
          var porcDevolucion = item.Promedio_Llevados > 0 ? (decimal)item.Promedio_Devueltos * 100 / item.Promedio_Llevados : 0;

          table.Cell().Border(1).Padding(3).Text(item.Dia);
          table.Cell().Border(1).Padding(3).AlignRight().Text(item.Cant.ToString("N0"));
          table.Cell().Border(1).Padding(3).AlignRight().Text(item.Promedio_Llevados.ToString("N0"));
          table.Cell().Border(1).Padding(3).AlignRight().Text(item.Promedio_Devueltos.ToString("N0"));
          table.Cell().Border(1).Padding(3).AlignRight().Text(item.Promedio_Ventas.ToString("N0"));
          table.Cell().Border(1).Padding(3).AlignRight().Text(porcDevolucion.ToString("F2") + "%");
        }

        // --- SECCIÓN AÑADIDA PARA LA FILA "GENERAL" ---
        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.Cant.ToString("N0")).Style(boldStyle));
          table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span(general.Promedio_Llevados.ToString("N0")).Style(boldStyle));
          table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span(general.Promedio_Devueltos.ToString("N0")).Style(boldStyle));
          table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span(general.Promedio_Ventas.ToString("N0")).Style(boldStyle));
          table.Cell().Border(1).Padding(3).AlignRight().Text(text => text.Span(Model.PorcentajeDevolucionGeneral.ToString("F2") + "%").Style(boldStyle));
        }
      });
      });
    }
  }
}