using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text;
using System.Text.Json;
using Auth.Contracts.DTOs.Auth;
using Auth.Contracts.DTOs.Users;
using Blazored.LocalStorage;
using Microsoft.AspNetCore.Components.Authorization;

namespace Auth.RCL.Services
{
    public class UserAPIConsumer
    {
        private readonly HttpClient client;
        private readonly AuthenticationStateProvider _authenticationStateProvider;
        private readonly ILocalStorageService _localStorage;

        public UserAPIConsumer(
            IHttpClientFactory httpClientFactory,
            AuthenticationStateProvider authenticationStateProvider,
            ILocalStorageService localStorage
        )
        {
            this.client = httpClientFactory.CreateClient("Auth");

            _authenticationStateProvider = authenticationStateProvider;
            _localStorage = localStorage;
        }

        public async Task<(bool IsSuccessful, string Message)> Register(RegisterModel registerModel)
        {
            try
            {
                var registerAsJson = JsonSerializer.Serialize(registerModel);
                var response = await client.PostAsync(
                    "auth/Register",
                    new StringContent(registerAsJson, Encoding.UTF8, "application/json")
                );

                return (response.IsSuccessStatusCode, await response.Content.ReadAsStringAsync());
            }
            catch (HttpRequestException ex)
            {
                // _logger.LogError(ex, "GET request failed for endpoint: {Endpoint}", endpoint);
                throw;
            }
        }

        public async Task RefreshToken(TokenModel tokenModel) { }

        public async Task<bool> Login(TokenRequestModel tokenRequestModel)
        {
            try
            {
                var loginAsJson = JsonSerializer.Serialize(tokenRequestModel);
                var response = await client.PostAsync(
                    "auth/login",
                    new StringContent(loginAsJson, Encoding.UTF8, "application/json")
                );

                if (response.IsSuccessStatusCode)
                {
                    var loginResult = JsonSerializer.Deserialize<LoginResult>(
                        await response.Content.ReadAsStringAsync(),
                        new JsonSerializerOptions { PropertyNameCaseInsensitive = true }
                    );
                    await _localStorage.SetItemAsync("authToken", loginResult.AccessToken);
                    await _localStorage.SetItemAsync("refreshToken", loginResult.RefreshToken);
                    await _localStorage.SetItemAsync("expiryDate", loginResult.Expiry);

                    (
                        (ApiAuthenticationStateProvider)_authenticationStateProvider
                    ).MarkUserAsAuthenticated(loginResult.AccessToken);
                    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
                        "bearer",
                        loginResult.AccessToken
                    );

                    loginResult.IsSuccessful = true;

                    return true;
                }

                return false;
            }
            catch (HttpRequestException ex)
            {
                // _logger.LogError(ex, "GET request failed for endpoint: {Endpoint}", endpoint);
                throw;
            }
        }

        public async Task Logout()
        {
            try
            {
                try
                {
                    await client.PostAsync("auth/logout", null);
                }
                catch { }

                await _localStorage.RemoveItemAsync("authToken");
                await _localStorage.RemoveItemAsync("refreshToken");
                await _localStorage.RemoveItemAsync("expiryDate");

                (
                    (ApiAuthenticationStateProvider)_authenticationStateProvider
                ).MarkUserAsLoggedOut();
                client.DefaultRequestHeaders.Authorization = null;
            }
            catch
            {
                throw;
            }
        }

        public async Task<UserVM> GetUserInfoAsync(string id)
        {
            try
            {
                var user = await client.GetFromJsonAsync<UserVM>($"user/{id}");
                return user;
            }
            catch
            {
                throw;
            }
        }

        public async Task<bool> UpdateUserInfoAsync(UserVM user)
        {
            try
            {
                var response = await client.PutAsJsonAsync("user", user);
                return response.IsSuccessStatusCode;
            }
            catch
            {
                throw;
            }
        }

        public async Task<List<UserVM>> GetUsers()
        {
            try
            {
                var users = await client.GetFromJsonAsync<List<UserVM>>($"users");
                return users;
            }
            catch
            {
                throw;
            }
        }

        public async Task<UserVM> GetUser(string id)
        {
            try
            {
                var user = await client.GetFromJsonAsync<UserVM>($"user/{id}");
                return user;
            }
            catch
            {
                throw;
            }
        }

        public async Task<bool> UpdateUser(UserInfoUpdate user)
        {
            try
            {
                var response = await client.PutAsJsonAsync("user", user);
                return response.IsSuccessStatusCode;
            }
            catch
            {
                throw;
            }
        }

        public async Task<bool> ResendConfirmation()
        {
            try
            {
                var response = await client.GetAsync("auth/resend-confirmation");
                return response.IsSuccessStatusCode;
            }
            catch
            {
                throw;
            }
        }

        public async Task<bool> RequestResetPassword(string email)
        {
            try
            {
                var response = await client.GetAsync($"auth/password-reset-token/{email}");
                return response.IsSuccessStatusCode;
            }
            catch
            {
                throw;
            }
        }

        public async Task<bool> ConfirmEmail(string token)
        {
            try
            {
                var response = await client.PostAsJsonAsync(
                    "auth/confirm-email",
                    token,
                    new JsonSerializerOptions() { PropertyNameCaseInsensitive = true }
                );
                return response.IsSuccessStatusCode;
            }
            catch
            {
                throw;
            }
        }

        public async Task<bool> ResetPassword(PasswordResetModel passwordResetModel)
        {
            try
            {
                var response = await client.PostAsJsonAsync(
                    "auth/reset-password",
                    passwordResetModel,
                    new JsonSerializerOptions() { PropertyNameCaseInsensitive = true }
                );
                return response.IsSuccessStatusCode;
            }
            catch
            {
                throw;
            }
        }

        public async Task<bool> SendPhoneNumberToken(string phoneNumber)
        {
            try
            {
                var result = await client.PostAsJsonAsync($"auth/phone-number", phoneNumber);
                return result.IsSuccessStatusCode;
            }
            catch
            {
                throw;
            }
        }

        public async Task<bool> UpdatePhoneNumber(UpdatePhoneNumber updatePhoneNumber)
        {
            try
            {
                var result = await client.PutAsJsonAsync($"auth/phone-number", updatePhoneNumber);
                return result.IsSuccessStatusCode;
            }
            catch
            {
                throw;
            }
        }

        public async Task<bool> SendChangeEmailToken(RequestChangeEmail requestChangeEmail)
        {
            try
            {
                var result = await client.PostAsJsonAsync($"auth/change-email", requestChangeEmail);
                return result.IsSuccessStatusCode;
            }
            catch
            {
                throw;
            }
        }
    }
}
