using Indotalent.ConfigBackEnd.Interfaces;
using Indotalent.Features.Account.Login.Cqrs;
using Indotalent.Infrastructure.Authentication.Identity;
using Indotalent.Shared.Models;
using Microsoft.AspNetCore.Components;
using MudBlazor;
using RestSharp;
using System.Net;

namespace Indotalent.ConfigFrontEnd.Common;

public abstract class BaseService
{
    protected readonly IHttpClientFactory ClientFactory;
    protected readonly NavigationManager Nav;
    protected readonly ISnackbar Snackbar;
    protected readonly ICurrentUserService CurrentUserService;
    protected readonly TokenProvider TokenProvider;

    public BaseService(
        IHttpClientFactory clientFactory,
        NavigationManager nav,
        ISnackbar snackbar,
        ICurrentUserService currentUserService,
        TokenProvider tokenProvider)
    {
        ClientFactory = clientFactory;
        Nav = nav;
        Snackbar = snackbar;
        CurrentUserService = currentUserService;
        TokenProvider = tokenProvider;
    }

    protected HttpClient CreateClient()
    {
        var client = ClientFactory.CreateClient();
        if (client.BaseAddress == null)
        {
            client.BaseAddress = new Uri(Nav.BaseUri);
        }
        return client;
    }

    protected async Task<ApiResponse<T>?> ExecuteWithResponseAsync<T>(RestClient client, RestRequest request)
    {
        try
        {
            if (!string.IsNullOrEmpty(TokenProvider.Token))
                request.AddOrUpdateHeader("Authorization", $"Bearer {TokenProvider.Token}");

            if (!string.IsNullOrEmpty(TokenProvider.RefreshToken))
                request.AddOrUpdateHeader("X-Refresh-Token", TokenProvider.RefreshToken);

            if (!string.IsNullOrEmpty(CurrentUserService.UserId))
            {
                request.AddOrUpdateHeader("X-UserId", CurrentUserService.UserId);
                request.AddOrUpdateHeader("X-UserName", CurrentUserService.UserName ?? string.Empty);
                request.AddOrUpdateHeader("X-Email", CurrentUserService.Email ?? string.Empty);
                request.AddOrUpdateHeader("X-FullName", CurrentUserService.FullName ?? string.Empty);
                request.AddOrUpdateHeader("X-TenantId", CurrentUserService.TenantId ?? string.Empty);
            }

            var response = await client.ExecuteAsync<ApiResponse<T>>(request);


            if (response.StatusCode == HttpStatusCode.Unauthorized)
            {
                var httpClient = CreateClient();

                var refreshRequestMessage = new HttpRequestMessage(HttpMethod.Post, "/api/account/refresh-token");

                if (!string.IsNullOrEmpty(TokenProvider.RefreshToken))
                {
                    refreshRequestMessage.Headers.Add("X-Refresh-Token", TokenProvider.RefreshToken);
                }

                var refreshResponse = await httpClient.SendAsync(refreshRequestMessage);

                if (refreshResponse.IsSuccessStatusCode)
                {
                    var result = await refreshResponse.Content.ReadFromJsonAsync<LoginResponse>();
                    if (result != null && !string.IsNullOrEmpty(result.Token))
                    {
                        TokenProvider.Token = result.Token;

                        request.AddOrUpdateHeader("Authorization", $"Bearer {TokenProvider.Token}");
                        response = await client.ExecuteAsync<ApiResponse<T>>(request);
                    }
                }
                else
                {
                    Nav.NavigateTo("/account/login");
                    return default;
                }
            }

            if (response.Data != null)
            {
                if (!response.Data.IsSuccess)
                {
                    HandleApiError(response.Data);
                }
                return response.Data;
            }

            var fallbackMessage = GetFriendlyInfrastructureErrorMessage(response);
            Snackbar.Add(fallbackMessage, Severity.Error);

            return new ApiResponse<T>
            {
                IsSuccess = false,
                StatusCode = (int)response.StatusCode,
                Message = fallbackMessage
            };
        }
        catch (Exception ex)
        {
            var systemError = $"Client System Error: {ex.Message}";
            Snackbar.Add(systemError, Severity.Error);
            return new ApiResponse<T> { IsSuccess = false, Message = systemError };
        }
    }

    private void HandleApiError<T>(ApiResponse<T> response)
    {
        var mainMessage = response.Message ?? "Operation failed";
        if (response.Errors != null && response.Errors.Any())
        {
            var combinedErrors = string.Join(Environment.NewLine, response.Errors.Select(e => $"• {e}"));
            Snackbar.Add(combinedErrors, Severity.Error, config =>
            {
                config.ShowCloseIcon = true;
                config.VisibleStateDuration = 3000;
            });
        }
        else
        {
            Snackbar.Add(mainMessage, Severity.Error);
        }
    }

    private string GetFriendlyInfrastructureErrorMessage(RestResponse response)
    {
        return response.StatusCode switch
        {
            HttpStatusCode.ServiceUnavailable => "Server is currently under maintenance.",
            HttpStatusCode.GatewayTimeout => "Server took too long to respond.",
            HttpStatusCode.Unauthorized => "Session expired. Please login again.",
            HttpStatusCode.Forbidden => "You do not have permission to access this resource.",
            HttpStatusCode.InternalServerError => "A critical error occurred on the server.",
            _ => "Unable to reach the server. Please check your connection."
        };
    }
}