using Butter.Dtos;
using Butter.Dtos.User;
using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage;
using Microsoft.Extensions.Options;
using System.Runtime.CompilerServices;

namespace MilkStream.Services;

public class LoginServiceOptions() {
    public string BaseUrl { get; set; } = string.Empty;
}

public class LoginService {
    HttpClient            client;
    ProtectedLocalStorage localStorage;
    public AuthInfo?      authInfo   { get; set; }
    public bool           IsLoggedIn => authInfo != null;

    public LoginService(IOptions<LoginServiceOptions> options, ProtectedLocalStorage localStorage) {
        client             = new HttpClient();
        client.BaseAddress = new Uri(options.Value.BaseUrl);
        client.DefaultRequestHeaders.Accept.Add(new("application/json"));
        this.localStorage = localStorage;
    }

    public async Task<bool> RetrieveAuthInfo() {
        try {
            var result = await localStorage.GetAsync<AuthInfo>("auth");

            if (result.Success) {
                authInfo = result.Value;
                return true;
            }
        } catch (Exception ex) { Console.WriteLine($"Error retrieving auth info: {ex.Message}"); }

        return false;
    }

    public async Task<(bool, AuthInfo?)> Login(string username, string password) {
        var loginDto = new CredentialsDto() {
            Identifier = username,
            Password   = password
        };

        var response = await client.PostAsJsonAsync("api/auth/login", loginDto);

        return response.IsSuccessStatusCode ?
            (true, response.Content.ReadFromJsonAsync<AuthResultDto>().Result!.ToAuthInfo()) :
            (false, null);
    }

    public async Task<AuthInfo> Reauthenticate() {
        if (authInfo == null) throw new InvalidOperationException("No authentication info available to reauthenticate.");

        var refreshDto = new RefreshDto() {
            UserId       = (Guid)this.authInfo.UserId,
            RefreshToken = authInfo.RefreshToken!
        };

        var result = await client.PostAsync("api/auth/refresh", JsonContent.Create(refreshDto)).ConfigureAwait(false);

        if (result.IsSuccessStatusCode) {
            var authResult = await result.Content.ReadFromJsonAsync<AuthResultDto>();
            authInfo.Token = authResult?.Token;
            return authInfo;
        } else { throw new Exception($"Failed to reauthenticate. Status code: {result.StatusCode}"); }
    }

    public async Task<bool> Register(string username, string email, string password) {
        var registerDto = new UserRegisterDto() {
            Username = username,
            Email    = email,
            Password = password
        };

        var response = await client.PostAsJsonAsync("api/auth/register", registerDto);

        return response.IsSuccessStatusCode;
    }

    public async Task<bool> Logout() {
        var response = await client.PostAsync("api/auth/logout", null);

        return response.IsSuccessStatusCode;
    }
}
