using Microsoft.Extensions.Logging;
using SpotifyAPI.Web;

public class SongResolver
{
    private readonly IEnumerable<ISongValidator> _songValidators;

    private readonly ILogger<SongResolver> logger;

    private SpotifyApiClient spotifyApiClient;

    public SongResolver(ILogger<SongResolver> logger, ILoggerFactory loggerFactory, SpotifyApiClient spotifyApiClient)
    {
        this.logger = logger;

        this._songValidators = new List<ISongValidator>();
        this.spotifyApiClient = spotifyApiClient;

        foreach (Type mytype in System.Reflection.Assembly.GetExecutingAssembly().GetTypes()
                 .Where(mytype => { return (mytype.GetInterfaces().Contains(typeof(ISongValidator)) && !(mytype.Name.Split("`")[0].EndsWith("Base"))); }))
        {
            var typedLogger = loggerFactory.CreateLogger(mytype);
            if (Activator.CreateInstance(mytype, typedLogger, spotifyApiClient) is ISongValidator validator)
            {
                logger.LogDebug("Registering song validator: {ValidatorType}", mytype.Name);
                this._songValidators = this._songValidators.Append(validator);
            }
        }
    }

    public async Task<Song> ResolveSongAsync(Uri songUri)
    {
        foreach (var validator in _songValidators)
        {
            if (validator.CanValidateUri(songUri))
            {
                if (!await validator.CanExtractSongMetadataAsync(songUri))
                {
                    this.logger.LogWarning("Cannot extract metadata for song URI: {SongUri}", songUri);
                    return new Song
                    {
                        Artist = "Unknown Artist",
                        Name = "Unknown Title",
                        Url = songUri.ToString(),
                        Provider = SongProvider.PlainHttp,
                    };
                }
                return await validator.ValidateAsync(songUri);
            }
        }

        return new Song
        {
            Artist = "Unknown Artist",
            Name = "Unknown Title",
            Url = songUri.ToString(),
            Provider = SongProvider.PlainHttp,
        };
    }

    public bool CanValidate(Uri songUri)
    {
        foreach (var validator in _songValidators)
        {
            if (validator.CanValidateUri(songUri))
            {
                return true;
            }
        }

        return false;
    }

    public async Task<Base64UrlImageBuilder> GetPreviewImageAsync(string spotifyId)
    {
        var track = await spotifyApiClient.GetTrackByIdAsync(spotifyId);
        var url = track.Album.Images.FirstOrDefault().Url;
        return new Base64UrlImageBuilder()
        {
            Url = url,
            ContentType = "image/jpeg"
        };
    }
}