using JSMR.Application.Integrations.DLSite.Models;
using JSMR.Domain.Enums;
using JSMR.Domain.ValueObjects;
using JSMR.Infrastructure.Http;
using JSMR.Infrastructure.Integrations.DLSite;
using JSMR.Infrastructure.Integrations.DLSite.Mapping;
using JSMR.Infrastructure.Integrations.DLSite.Models;
using JSMR.Tests.Utilities;
using Microsoft.Extensions.Logging;
using NSubstitute;
using Shouldly;

namespace JSMR.Tests.Integrations.DLSite;

public class DLSiteClientTests
{
    private static async Task<string> ReadJsonResourceAsync(string resourceName)
    {
        return await ResourceHelper.ReadAsync($"JSMR.Tests.Integrations.DLSite.{resourceName}");
    }

    [Fact]
    public async Task Deserialize_Product_Info_Collection()
    {
        string productInfoJson = await ReadJsonResourceAsync("Product-Info.json");

        IHttpService httpService = Substitute.For<IHttpService>();

        httpService.GetStringAsync(Arg.Any<string>(), CancellationToken.None)
            .Returns(Task.FromResult(productInfoJson));

        var logger = Substitute.For<ILogger<DLSiteClient>>();
        var client = new DLSiteClient(httpService, logger);

        var result = await client.GetVoiceWorkDetailsAsync(["RJ01230163"], CancellationToken.None);

        result.Count.ShouldBe(1);

        result.ShouldContainKey("RJ01230163");
        result["RJ01230163"].HasTrial.ShouldBeTrue();
        result["RJ01230163"].HasDLPlay.ShouldBeTrue();
        result["RJ01230163"].HasReviews.ShouldBeTrue();
        result["RJ01230163"].SupportedLanguages.Count.ShouldBe(1);
        result["RJ01230163"].SupportedLanguages.Select(x => x.Language).ShouldContain(Language.English);
        result["RJ01230163"].DownloadCount.ShouldBe(659);
        result["RJ01230163"].WishlistCount.ShouldBe(380);
    }

    [Fact]
    public void Map_Basic_ProductInfoCollection()
    {
        ProductInfoCollection productInfoCollection = new()
        {
            {
                "RG0001",
                new ProductInfo()
                {
                    WishlistCount = 250,
                    DownloadCount = 100,
                    Options = ["TRI", "DLP", "JPN"],
                    TitleId = "SE0001",
                    TitleName = "Series 1"
                }
            },
            {
                "RG0002",
                new ProductInfo()
                {
                    WishlistCount = 100,
                    DownloadCount = 50,
                    Options = ["TRI", "ENG", "DOT", "VET"],
                    TitleId = "SE0001",
                    TitleName = "Series 1",
                    TranslationInfo = new()
                    {
                        OriginalWorkNumber = "RG0001",
                        Language = "ENG"
                    }
                }
            }
        };

        // General
        VoiceWorkDetailCollection mappedCollection = DLSiteToDomainMapper.Map(productInfoCollection);
        mappedCollection.Count.ShouldBe(2);
        mappedCollection.ShouldContainKey("RG0001");
        mappedCollection.ShouldContainKey("RG0002");

        // RG0001
        VoiceWorkDetails voiceWorkDetails = mappedCollection["RG0001"];
        voiceWorkDetails.WishlistCount.ShouldBe(250);
        voiceWorkDetails.DownloadCount.ShouldBe(100);
        voiceWorkDetails.HasTrial.ShouldBe(true);
        voiceWorkDetails.HasDLPlay.ShouldBe(true);
        voiceWorkDetails.AI.ShouldBe(AIGeneration.None);
        voiceWorkDetails.SupportedLanguages.ShouldBe([SupportedLanguage.Japanese]);

        voiceWorkDetails.Series.ShouldNotBeNull();
        voiceWorkDetails.Series.Identifier.ShouldBe("SE0001");
        voiceWorkDetails.Series.Name.ShouldBe("Series 1");


        // RG0002
        VoiceWorkDetails secondVoiceWorkDetails = mappedCollection["RG0002"];
        secondVoiceWorkDetails.WishlistCount.ShouldBe(100);
        secondVoiceWorkDetails.DownloadCount.ShouldBe(50);
        secondVoiceWorkDetails.HasTrial.ShouldBe(true);
        secondVoiceWorkDetails.HasDLPlay.ShouldBe(false);
        secondVoiceWorkDetails.AI.ShouldBe(AIGeneration.None);
        secondVoiceWorkDetails.SupportedLanguages.ShouldBe([SupportedLanguage.English]);

        secondVoiceWorkDetails.Series.ShouldNotBeNull();
        secondVoiceWorkDetails.Series.Identifier.ShouldBe("SE0001");
        secondVoiceWorkDetails.Series.Name.ShouldBe("Series 1");

        secondVoiceWorkDetails.Translation.ShouldNotBeNull();
        secondVoiceWorkDetails.Translation.OriginalProductId.ShouldBe("RG0001");
        secondVoiceWorkDetails.Translation.Language.ShouldBe(Language.English);
        secondVoiceWorkDetails.Translation.Kind.ShouldBe(TranslationKind.Official | TranslationKind.Recommended);
    }
}