using Microsoft.Extensions.Logging;
using ProjectShoeShop.Repositories;

namespace ProjectShoeShop.Reports;

internal class TableReport
{
    private readonly IOrderRepository _orderRepository;
    private readonly ISupplyRepository _supplyRepository;
    private readonly ILogger<TableReport> _logger;
    internal static readonly string[] item = ["Дата", "Количество пришло", "Количество ушло"];

    public TableReport(IOrderRepository orderRepository, ISupplyRepository supplyRepository, ILogger<TableReport> logger)
    {
        _orderRepository = orderRepository ?? throw new ArgumentNullException(nameof(orderRepository));
        _supplyRepository = supplyRepository ?? throw new ArgumentNullException(nameof(supplyRepository));
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    public bool CreateTable(string filePath, int shoesId, DateTime startDate, DateTime endDate)
    {
        try
        {
            new ExcelBuilder(filePath)
                .AddHeader("Сводка по движению товара", 0, 3)
                .AddParagraph("за период", 0)
                .AddTable([10, 15, 15], GetData(shoesId, startDate, endDate))
                .Build();
            return true;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Ошибка при формировании документа");
            return false;
        }
    }

    private List<string[]> GetData(int shoesId, DateTime startDate, DateTime endDate)
    {
        var data = _orderRepository
            .ReadOrder()
            .Where(x => x.OrderDate >= startDate && x.OrderDate <= endDate && x.OrderItems.Any(y => y.ShoesId == shoesId))
            .Select(x => new { Date = x.OrderDate.Date, CountIn = (int?)null, CountOut = x.OrderItems.FirstOrDefault(y => y.ShoesId == shoesId)?.NumberOfPairs })
            .Union(
                _supplyRepository
                .ReadSupply()
                .Where(x => x.DateOfReceipt >= startDate && x.DateOfReceipt <= endDate && x.SupplyShoes.Any(y => y.ShoesId == shoesId))
                .Select(x => new { Date = x.DateOfReceipt.Date, CountIn = x.SupplyShoes.FirstOrDefault(y => y.ShoesId == shoesId)?.NumberOfPairs, CountOut = (int?)null })
            )
            .OrderBy(x => x.Date);

        var groupedData = data
            .GroupBy(x => x.Date)
            .Select(g => new
            {
                Date = g.Key,
                TotalIn = g.Sum(x => x.CountIn),
                TotalOut = g.Sum(x => x.CountOut)
            })
            .OrderBy(x => x.Date);
        return
            new List<string[]>() { item }
            .Union(groupedData
            .Select(x => new string[] { x.Date.ToString("dd.MM.yyyy"), x.TotalIn.ToString()!, x.TotalOut.ToString()! }))
            .Union(
                new[] { new string[] { "Всего", groupedData.Sum(x => x.TotalIn).ToString()!, groupedData.Sum(x => x.TotalOut).ToString()! } }
            )
            .ToList();
    }
}
