using System.Net;
using System.Net.Http.Headers;
using Lightquark.NET.Objects.Reply;
using Newtonsoft.Json;

namespace Lightquark.NET;

public partial class Client
{
    private Timer? _refreshTimer;
    
    public async Task<(bool success, string error, string? accessToken, string? refreshToken)> AcquireToken(string email, string password)
    {
        try
        {
            var finalUri = new Uri(new Uri(NetworkInformation!.BaseUrl!), $"{Version}/auth/token");
            Console.WriteLine($"{finalUri}");
            var res = await _httpClient.PostAsync(finalUri, new StringContent(JsonConvert.SerializeObject(new
            {
                email, password
            }), new MediaTypeHeaderValue("application/json")));
            var parsedRes = JsonConvert.DeserializeObject<Reply<AuthReplyResponse>>(await res.Content.ReadAsStringAsync());

            if (parsedRes == null)
            {
                throw new Exception("Parsing failure");
            }
            
            switch (res.StatusCode)
            {
                case HttpStatusCode.OK:
                    UseToken(parsedRes.Response.AccessToken!, parsedRes.Response.RefreshToken!);
                    return (true, string.Empty, AccessToken, RefreshToken);
                case HttpStatusCode.BadRequest:
                case HttpStatusCode.Forbidden:
                    return (false, parsedRes.Response.Message, null, null);
                default:
                    return (false, $"Unknown problem logging in {res.StatusCode}", null, null);
            
            }
            
        }
        catch (Exception ex)
        {
            return (false, $"Failed to log in ({ex.Message})", null, null);
        }
    }

    public void UseToken(string? accessToken, string refreshToken)
    {
        RefreshToken = refreshToken;
        AccessToken = accessToken;
    }

    private async void AcquireToken(object? state = null)
    {
        Console.WriteLine($"Refreshing token {AccessToken} {RefreshToken}");
        try
        {
            var finalUri = new Uri(new Uri(NetworkInformation!.BaseUrl!), $"{Version}/auth/refresh");
            Console.WriteLine($"{finalUri}");
            var res = await _httpClient.PostAsync(finalUri, new StringContent(JsonConvert.SerializeObject(new
            {
                accessToken = AccessToken, refreshToken = RefreshToken
            }), new MediaTypeHeaderValue("application/json")));
            var parsedRes = JsonConvert.DeserializeObject<Reply<RefreshReplyResponse>>(await res.Content.ReadAsStringAsync());

            if (parsedRes == null)
            {
                throw new Exception("Parsing failure");
            }
            
            switch (res.StatusCode)
            {
                case HttpStatusCode.OK:
                    AccessToken = parsedRes.Response.AccessToken;
                    Console.WriteLine("Token refreshed! Happy days.");
                    break;
                default:
                    await Console.Error.WriteLineAsync($"Failed to refresh ({res.StatusCode}) ({parsedRes?.Response?.Message})");
                    AccessToken = null;
                    RefreshToken = null;
                    break;
            }
            
        }
        catch (Exception ex)
        {
            Console.Error.WriteLine(ex);
            await Console.Error.WriteLineAsync($"Failed to log in ({ex.Message})");
        }
    }

    public void LogOut()
    {
        AccessToken = null;
        RefreshToken = null;
    }

    public void RunLogOut()
    {
        Console.WriteLine("Logging out!");
        OnLogOut?.Invoke();
        _refreshTimer?.Dispose();
    }
}