using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text.Json;
using System.Threading.Tasks;
using Avalonia.Controls;
using Avalonia.Controls.Shapes;
using Avalonia.Media.Imaging;
using Avalonia.Platform;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;

namespace LOLRLCG.ViewModels;

public class ChampionWrapper
{
    public Dictionary<string, Champion> Data { get; set; }
}

public class ImageInfo
{
    public string Full { get; set; }
}

public class Champion : ObservableObject
{
    public string Id { get; init; }
    private string _name;
    public string Title { get; init; }
    public List<string> Tags { get; init; }
    public string? Uri { get; init; }
    public ImageInfo Image { get; set; }
    private Bitmap? _imageBitmap;

    public string Name
    {
        get => _name;
        set => SetProperty(ref _name, value);
    }

    public Bitmap? ImageBitmap
    {
        get => _imageBitmap;
        set => SetProperty(ref _imageBitmap, value);
    }
    
    public Champion(string id, string name, string title, List<string> tags, ImageInfo image, string? uri = null)
    {
        this.Id = id;
        this.Name = name;
        this.Title = title;
        this.Tags = tags;
        this.Image = image;
    }
}

public partial class MainWindowViewModel : ViewModelBase
{
    private HttpClient httpClient = new HttpClient();
    private List<string> Lanes = new List<string>(["Top", "Mid", "Bot", "Sup", "Jgl"]);

    private List<Champion>? _championList;
    private Champion? _selectedChampion;

    private string? _lane;
    private Bitmap? _laneImage;

    private string? _leagueClientVersion;

    private int _topPercentage = 100;
    private int _midPercentage = 100;
    private int _jglPercentage = 100;
    private int _botPercentage = 100;
    private int _supPercentage = 100;
    
    public RelayCommand getRandomChampionLaneComboCommand { get; private set; }
    
    public List<Champion>? ChampionList
    {
        get => _championList;
        set => SetProperty(ref _championList, value);
    }
    
    public Champion? SelectedChampion
    {
        get => _selectedChampion;
        set => SetProperty(ref _selectedChampion, value);
    }

    public string Lane
    {
        get => _lane;
        set => SetProperty(ref _lane, value);
    }
    
    public Bitmap? LaneImage
    {
        get => _laneImage;
        set => SetProperty(ref _laneImage, value);
    }

    public string? LeagueClientVersion
    {
        get => _leagueClientVersion;
        set => SetProperty(ref _leagueClientVersion, value);
    }

    public int TopPercentage
    {
        get => _topPercentage;
        set => SetProperty(ref _topPercentage, value);
    }
    
    public int MidPercentage
    {
        get => _midPercentage;
        set => SetProperty(ref _midPercentage, value);
    }
    
    public int JglPercentage
    {
        get => _jglPercentage;
        set => SetProperty(ref _jglPercentage, value);
    }
    
    public int BotPercentage
    {
        get => _botPercentage;
        set => SetProperty(ref _botPercentage, value);
    }
    
    public int SupPercentage
    {
        get => _supPercentage;
        set => SetProperty(ref _supPercentage, value);
    }
    
    private async void LoadAndSetChampionImageAsync()
    {
        // champ.Uri = $"http://ddragon.leagueoflegends.com/cdn/{LeagueClientVersion}/img/champion/{champ.Image.Full}";
        if(SelectedChampion != null)
            SelectedChampion.ImageBitmap = await LoadChampionImageAsync();
    }
    
    private async Task<Bitmap?> LoadChampionImageAsync()
    {
        var imageUrl = $"http://ddragon.leagueoflegends.com/cdn/{LeagueClientVersion}/img/champion/{SelectedChampion.Image.Full}";
        try
        {
            var bytes = await httpClient.GetByteArrayAsync(imageUrl);
            using var ms = new MemoryStream(bytes);
            return await Task.Run(() => new Bitmap(ms));
        }
        catch
        {
            return null;
        }
    }

    private async Task<string> getClientVersion()
    {
        try
        {
            var versionStr = await httpClient.GetStringAsync("https://ddragon.leagueoflegends.com/api/versions.json");
            var versions = JsonSerializer.Deserialize<List<string>>(versionStr);
            return versions?[0] ?? "Unavailable";
        }
        catch
        {
            return "Unavailable";
        }
    }
    
    private async Task getChampions()
    {
        LeagueClientVersion = await getClientVersion();
        if (LeagueClientVersion == "Unavailable") return;

        try
        {
            var url = $"http://ddragon.leagueoflegends.com/cdn/{LeagueClientVersion}/data/de_DE/champion.json";
            var json = await httpClient.GetStringAsync(url);
            var options = new JsonSerializerOptions
            {
                PropertyNameCaseInsensitive = true,
                IgnoreReadOnlyProperties = true,
                AllowTrailingCommas = true,
                DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull
            };

            var wrapper = JsonSerializer.Deserialize<ChampionWrapper>(json, options);
            
            _championList = wrapper?.Data?.Values.ToList() ?? new List<Champion>();
        }
        catch (Exception ex)
        {
            Console.WriteLine("Failed to load Champions: " + ex.Message);
        }
    }

    private void getRandomLane()
    {
        var weights = new Dictionary<string, int>
        {
            { "Top", TopPercentage },
            { "Mid", MidPercentage },
            { "Jgl", JglPercentage },
            { "Bot", BotPercentage },
            { "Sup", SupPercentage },
        };

        var totalWeight = weights.Values.Sum();
        if (totalWeight <= 0)
        {
            Lane = Lanes[Random.Shared.Next(Lanes.Count)];
            return;
        }

        var roll = Random.Shared.Next(totalWeight);

        var x = 0;
        foreach (var kv in weights)
        {
            x += kv.Value;
            if (roll < x)
            {
                Lane = kv.Key;
                return;
            }
        }

        // 5) Sicherheitshalber (wegen Rundungsfehlern)
        Lane = weights.Keys.Last();
    }
    
    private async void getRandomChampionLaneComboCommandExecute()
    {
        if (_championList == null) await InitAsync();
        var champ = _championList?[Random.Shared.Next(_championList.Count)];
        if (champ != null)
        {
            // champ.Image.Full = await LoadChampionImageAsync(champ);
            SelectedChampion = champ;
            LoadAndSetChampionImageAsync();
        }     
        getRandomLane();
    }

    public async Task InitAsync()
    {
        await getClientVersion();
        await getChampions();
    }
    
    public MainWindowViewModel()
    {
        _ = InitAsync();
        getRandomChampionLaneComboCommand = new RelayCommand(getRandomChampionLaneComboCommandExecute);
        getRandomChampionLaneComboCommandExecute();
    }
}