using Microsoft.EntityFrameworkCore;
using TeleWave.Application.Settings.GetSiteSettings;
using TeleWave.Application.Settings.UpdateSiteSettings;
using TeleWave.Application.Tests.Support;
using TeleWave.Infrastructure.Settings;
using Xunit;

namespace TeleWave.Application.Tests.Settings;

/// <summary>
/// Глобальные настройки сайта поверх key-value таблицы: значения по умолчанию, upsert (второй раз
/// пишем в ту же строку, а не заводим новую) и нормализация списка языков.
/// </summary>
public class SiteSettingsTests
{
    [Fact]
    public async Task Get_WithoutStoredValues_ReturnsDefaults()
    {
        var fixture = new TestDb();
        await using var db = fixture.New();

        var dto = await new GetSiteSettingsQueryHandler(new SiteSettings(db)).Handle(
            new GetSiteSettingsQuery(),
            CancellationToken.None
        );

        // Открытая регистрация и переключение по номерам по умолчанию выключены.
        Assert.False(dto.RegistrationEnabled);
        Assert.False(dto.ChannelNumbersEnabled);
        Assert.Equal(string.Empty, dto.PreferredAudioLanguages);
    }

    [Fact]
    public async Task Update_StoresValues_AndNormalizesLanguages()
    {
        var fixture = new TestDb();

        await using (var db = fixture.New())
        {
            var result = await new UpdateSiteSettingsCommandHandler(new SiteSettings(db)).Handle(
                new UpdateSiteSettingsCommand(true, " RUS , ,eng ", true),
                CancellationToken.None
            );
            Assert.True(result.IsSuccess);
            // Сохранение — за UnitOfWorkBehavior команды, в тесте делаем его руками.
            await db.SaveChangesAsync(CancellationToken.None);
        }

        await using (var db = fixture.New())
        {
            var dto = await new GetSiteSettingsQueryHandler(new SiteSettings(db)).Handle(
                new GetSiteSettingsQuery(),
                CancellationToken.None
            );
            Assert.True(dto.RegistrationEnabled);
            Assert.True(dto.ChannelNumbersEnabled);
            Assert.Equal("rus,eng", dto.PreferredAudioLanguages);
        }
    }

    [Fact]
    public async Task Update_Twice_RewritesSameRows()
    {
        var fixture = new TestDb();

        foreach (var enabled in new[] { true, false })
        {
            await using var db = fixture.New();
            await new UpdateSiteSettingsCommandHandler(new SiteSettings(db)).Handle(
                new UpdateSiteSettingsCommand(enabled, "rus", enabled),
                CancellationToken.None
            );
            await db.SaveChangesAsync(CancellationToken.None);
        }

        await using var verify = fixture.New();
        var settings = new SiteSettings(verify);
        // Ключей ровно три — повторная запись обновляет строку, а не добавляет вторую.
        Assert.Equal(3, await verify.AppSettings.CountAsync());
        Assert.False(await settings.IsRegistrationEnabledAsync(CancellationToken.None));
        Assert.Equal("rus", await settings.GetPreferredAudioLanguagesAsync(CancellationToken.None));
        Assert.False(await settings.AreChannelNumbersEnabledAsync(CancellationToken.None));
    }
}
