using JSMR.Application.Enums;
using JSMR.Application.Integrations.DLSite.Models.ReleasedWorks;
using JSMR.Application.Integrations.DLSite.Ports;
using JSMR.Application.Scanning.Contracts;
using JSMR.Application.Scanning.Ports;

namespace JSMR.Infrastructure.Scanning;

public class ReleasedWorksProvider(IDLSiteClient dlsiteClient) : IReleasedWorksProvider
{
    private const int MaxPeriodDays = 60;

    public async Task<ReleasedWorksCollection> GetReleasedWorksAsync(VoiceWorkScanResult scanResult, CancellationToken cancellationToken)
    {
        DateOnly[] salesDates =
        [
            .. scanResult.Works
                .Where(x => x.SalesDate.HasValue)
                .Select(x => x.SalesDate!.Value)
        ];

        if (salesDates.Length == 0)
            return [];

        HashSet<string> productIds = [.. scanResult.Works.Select(x => x.ProductId)];

        DateOnly minDate = salesDates.Min();
        DateOnly maxDate = salesDates.Max();

        ReleasedWorksCollection collection = [];

        DateOnly chunkStart = minDate;

        while (chunkStart <= maxDate)
        {
            int endDayNumber = Math.Min(chunkStart.DayNumber + MaxPeriodDays - 1, maxDate.DayNumber);
            DateOnly chunkEnd = DateOnly.FromDayNumber(endDayNumber);

            int period = chunkEnd.DayNumber - chunkStart.DayNumber + 1;

            ReleasedWorksRequest request = new(
                Locale: Locale.English,
                Date: chunkEnd,
                Period: period);

            ReleasedWorksCollection chunk = await dlsiteClient.GetReleasedWorksAsync(request, cancellationToken);

            foreach (string productId in chunk.Keys)
            {
                if (productIds.Contains(productId) == false)
                    continue;

                if (collection.ContainsKey(productId))
                    continue;

                collection.Add(productId, chunk[productId]);
            }

            chunkStart = chunkEnd.AddDays(1);
        }

        return collection;
    }

    //public async Task<ReleasedWorksCollection> GetReleasedWorksAsync(VoiceWorkScanResult scanResult, CancellationToken cancellationToken)
    //{
    //    DateOnly[] salesDates =
    //    [
    //        .. scanResult.Works
    //            .Where(x => x.SalesDate.HasValue)
    //            .Select(x => x.SalesDate!.Value)
    //    ];

    //    if (salesDates.Length == 0)
    //        return [];

    //    DateOnly minDate = salesDates.Min();
    //    DateOnly maxDate = salesDates.Max();

    //    DateOnly requestDate = minDate.AddDays(-1);
    //    DateOnly requestEndDate = maxDate.AddDays(1);

    //    int period = (requestEndDate.DayNumber - requestDate.DayNumber) + 1;

    //    ReleasedWorksRequest releasedWorksRequest = new(
    //        Locale: Locale.English,
    //        Date: requestEndDate,
    //        Period: period
    //    );

    //    return await dlsiteClient.GetReleasedWorksAsync(releasedWorksRequest, cancellationToken);
    //}
}