using Microsoft.EntityFrameworkCore;
using TeleWave.Application.Common.Interfaces;
using TeleWave.Domain.Library;

namespace TeleWave.Application.Library.Genres;

/// <summary>
/// Сопоставляет сырые обозначения жанров от внешних источников со справочником. Порядок исходного
/// списка сохраняется: первый распознанный жанр становится основным у шоу, а провайдеры отдают
/// жанры по убыванию значимости.
///
/// Нераспознанные обозначения молча отбрасываются: у шоу останутся те жанры, которые справочник
/// знает, а расширить справочник — задача администратора (см. псевдонимы жанра).
/// </summary>
public sealed class GenreMatcher(IAppDbContext dbContext)
{
    public async Task<IReadOnlyList<Guid>> MatchAsync(
        IEnumerable<string>? rawGenres,
        CancellationToken cancellationToken
    )
    {
        var normalized = (rawGenres ?? [])
            .Select(GenreAlias.Normalize)
            .Where(value => value.Length > 0)
            .Distinct(StringComparer.Ordinal)
            .ToList();

        if (normalized.Count == 0)
            return [];

        var byValue = await dbContext
            .GenreAliases.AsNoTracking()
            .Where(a => normalized.Contains(a.Value))
            .ToDictionaryAsync(a => a.Value, a => a.GenreId, cancellationToken);

        var result = new List<Guid>();
        foreach (var value in normalized)
        {
            // Один жанр приходит несколькими обозначениями (идентификатор + название) — берём первое
            // распознанное, дубликаты пропускаем.
            if (byValue.TryGetValue(value, out var genreId) && !result.Contains(genreId))
                result.Add(genreId);
        }

        return result;
    }
}
