using JSMR.Application.Scanning.Contracts;
using JSMR.Domain.Entities;
using JSMR.Infrastructure.Data;
using JSMR.Tests.Fixtures;
using JSMR.Tests.Ingestion.Japanese;
using Microsoft.EntityFrameworkCore;
using Shouldly;

namespace JSMR.Tests.Ingestion.Search;

internal record SearchRelatedParameters(
    string ProductId,
    string MakerId,
    string Title,
    string Description,
    string MakerName,
    string[] Tags,
    string[] Creators
);

public class Insert_Into_Search_Tests(MariaDbContainerFixture container) : JapaneseIngestionTestsBase(container)
{
    [Fact]
    public async Task Insert_Into_Search_And_Update()
    {
        await using AppDbContext dbContext = await GetAppDbContextAsync();

        // PART 1 - Insert
        SearchRelatedParameters parameters = new(
            ProductId: "RJ1",
            MakerId: "RG1",
            Title: "Title",
            Description: "Description",
            MakerName: "Maker",
            Tags: ["Tag 1", "Tag 2"],
            Creators: ["Creator 1"]
        );

        VoiceWorkIngest ingest = IngestTestFactory.Create(parameters);

        await UpsertAndVerify(dbContext, ingest, "RJ1 RG1 Title Description Maker Tag 1 Tag 2 Creator 1");

        // PART 2 - Update
        SearchRelatedParameters updateParameters = parameters with
        {
            Title = "Updated Title",
            Tags = ["Tag 1", "Tag 2", "Tag 3"]
        };

        VoiceWorkIngest updatedIngest = IngestTestFactory.Create(updateParameters);

        await UpsertAndVerify(dbContext, updatedIngest, "RJ1 RG1 Updated Title Description Maker Tag 1 Tag 2 Tag 3 Creator 1");
    }

    private static async Task UpsertAndVerify(AppDbContext dbContext, VoiceWorkIngest ingest, string searchText)
    {
        await UpsertAsync(dbContext, TokyoLocalToUtc(2025, 01, 15, 00, 00, 00), [ingest]);

        VoiceWork? voiceWork = await dbContext.VoiceWorks.SingleAsync(v => v.ProductId == ingest.ProductId, TestContext.Current.CancellationToken);
        voiceWork.ShouldNotBeNull();

        await UpdateSearchAsync(dbContext, [voiceWork.VoiceWorkId]);

        VoiceWorkSearch voiceWorkSearch = await dbContext.VoiceWorkSearches.SingleAsync(v => v.VoiceWorkId == voiceWork.VoiceWorkId, TestContext.Current.CancellationToken);
        voiceWorkSearch.ShouldNotBeNull();

        voiceWorkSearch.SearchText.ShouldBe(searchText);
    }
}