using System.Text.Json;
using System.Text.Json.Serialization;
using YandexMusic.API.Models.Common;
using YandexMusic.API.Models.Search.Album;
using YandexMusic.API.Models.Search.Artist;
using YandexMusic.API.Models.Search.Playlist;
using YandexMusic.API.Models.Search.Track;
using YandexMusic.API.Models.Search.Video;

namespace YandexMusic.API.Models.Search;

/// <summary>Конвертер для лучшего результата поиска (поле Best). Десериализует в конкретный тип в зависимости от значения поля type.</summary>
public class YSearchBestConverter : JsonConverter<YSearchBest>
{
    public override YSearchBest? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        if (reader.TokenType != JsonTokenType.StartObject)
            throw new JsonException("Ожидается объект Best");

        using var doc = JsonDocument.ParseValue(ref reader);
        var root = doc.RootElement;

        var typeProp = root.GetProperty("type");
        var typeStr = typeProp.GetString();
        if (!Enum.TryParse<YSearchType>(typeStr, true, out var searchType))
            throw new JsonException($"Неизвестный тип поиска: {typeStr}");

        var resultElement = root.GetProperty("result");
        var resultRaw = resultElement.GetRawText();

        object? result = null;

        switch (searchType)
        {
            case YSearchType.Track:
                result = JsonSerializer.Deserialize<YSearchTrackModel>(resultRaw, options);
                break;
            case YSearchType.Album:
                result = JsonSerializer.Deserialize<YSearchAlbumModel>(resultRaw, options);
                break;
            case YSearchType.Artist:
                result = JsonSerializer.Deserialize<YSearchArtistModel>(resultRaw, options);
                break;
            case YSearchType.Playlist:
                result = JsonSerializer.Deserialize<YSearchPlaylistModel>(resultRaw, options);
                break;
            case YSearchType.PodcastEpisode:
                result = JsonSerializer.Deserialize<YSearchTrackModel>(resultRaw, options);
                break;
            case YSearchType.Video:
                result = JsonSerializer.Deserialize<YSearchVideoModel>(resultRaw, options);
                break;
            default:
                result = null;
                break;
        }

        return new YSearchBest
        {
            Type = searchType,
            Result = result
        };
    }

    public override void Write(Utf8JsonWriter writer, YSearchBest value, JsonSerializerOptions options)
    {
        writer.WriteStartObject();
        writer.WriteString("type", value.Type.ToString().ToLowerInvariant());
        writer.WritePropertyName("result");
        JsonSerializer.Serialize(writer, value.Result, options);
        writer.WriteEndObject();
    }
}