using System.Collections.ObjectModel;
using System.ComponentModel;
using CommunityToolkit.Mvvm.ComponentModel;
using Lightquark.NET.Objects;
using Lightquark.NET.Util.Converters;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

namespace Lightquark.NET;

public partial class Client : ObservableObject
{
    private const string Version = "v4";
    public ObservableCollection<Quark> Quarks { get; set; } = [];
    public ObservableCollection<Channel> Channels { get; set; } = [];
    public ObservableCollection<Message> Messages { get; set; } = [];
    public Action? OnLogOut;

    private string? _accessToken;
    private string? AccessToken
    {
        get => _accessToken;
        set => SetProperty(ref _accessToken, value);
    }

    private string? _refreshToken;
    private string? RefreshToken {
        get => _refreshToken;
        set => SetProperty(ref _refreshToken, value);
    }

    public EnrichedNetworkInformation? NetworkInformation
    {
        get => _networkInformation;
        set => SetProperty(ref _networkInformation, value);
    }

    private EnrichedNetworkInformation? _networkInformation;
    private HttpClient _httpClient = new();

    public Client()
    {
        JsonConvert.DefaultSettings = () => new JsonSerializerSettings
        {
            Formatting = Formatting.Indented,
            NullValueHandling = NullValueHandling.Ignore,
            Converters = new List<JsonConverter> { new AttachmentCreationConverter() },
            ContractResolver = new CamelCasePropertyNamesContractResolver()
        };
    }

    
    protected override void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        if (e.PropertyName == "AccessToken" && AccessToken != null)
        {
            var tokenParts = AccessToken.Split(".");
            var expirationTimePart = tokenParts[4];
            var expiryTime = Base36Converter.ConvertFrom(expirationTimePart);
            var origin = new DateTimeOffset(1970, 1, 1, 0, 0, 0, 0, TimeSpan.Zero);
            var expiryDate = origin.AddMilliseconds(expiryTime);
            Console.WriteLine($"Token expires at {expiryDate}");
            var refreshTime = expiryDate.Subtract(TimeSpan.FromMinutes(15));
            var timeUntilRefresh = refreshTime - DateTimeOffset.Now;
            if (timeUntilRefresh < TimeSpan.FromSeconds(1))
            {
                AcquireToken();
            }
            else
            {
                if (_refreshTimer != null)
                {
                    _refreshTimer.Change(timeUntilRefresh, Timeout.InfiniteTimeSpan);
                }
                else
                {
                    _refreshTimer = new Timer(AcquireToken, null, timeUntilRefresh, Timeout.InfiniteTimeSpan);
                }
            }
        }
        Console.WriteLine($"Detected {e.PropertyName} change");

        if (e.PropertyName == "RefreshToken" && RefreshToken == null)
        {
            Console.WriteLine("Detected LogOut");
            RunLogOut();
        }
        base.OnPropertyChanged(e);
    }
}