using System.Net.Http.Json;
using System.Text.Json;
using Microsoft.JSInterop;

namespace DiunaBI.UI.Shared.Services;

public class UserInfo
{
    public Guid Id { get; set; }
    public string FullName { get; set; } = string.Empty;
    public string Email { get; set; } = string.Empty;
    public string AvatarUrl { get; set; } = string.Empty;
}
public class AuthService
{
    private readonly HttpClient _httpClient;
    private readonly IJSRuntime _jsRuntime;
    private bool? _isAuthenticated;
    private UserInfo? _userInfo = null;
    private string? _apiToken;
    
    public event Action<bool>? AuthenticationStateChanged;
    
    public AuthService(HttpClient httpClient, IJSRuntime jsRuntime)
    {
        _httpClient = httpClient;
        _jsRuntime = jsRuntime;
    }
    
    public bool IsAuthenticated => _isAuthenticated ?? false;
    public UserInfo? CurrentUser => _userInfo;
    
    public async Task<(bool success, string? errorMessage)> ValidateWithBackendAsync(string googleCredential, string fullName, string email, string avatarUrl)
    {
        try
        {
            Console.WriteLine($"=== ValidateWithBackend: Sending Google credential for {email} ===");
            
            var response = await _httpClient.PostAsJsonAsync("Auth/apiToken", googleCredential);
            
            if (response.IsSuccessStatusCode)
            {
                var result = await response.Content.ReadFromJsonAsync<ApiTokenResponse>();
                if (result != null)
                {
                    _apiToken = result.Token;
                    _userInfo = new UserInfo
                    {
                        Id = result.Id,
                        FullName = fullName,
                        Email = email,
                        AvatarUrl = avatarUrl
                    };
                    
                    await _jsRuntime.InvokeVoidAsync("localStorage.setItem", "api_token", _apiToken);
                    await _jsRuntime.InvokeVoidAsync("localStorage.setItem", "user_info", JsonSerializer.Serialize(_userInfo));
                    
                    _httpClient.DefaultRequestHeaders.Authorization = 
                        new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _apiToken);
                    
                    _isAuthenticated = true;
                    Console.WriteLine($"✅ Backend validation successful. UserId={result.Id}");
                    AuthenticationStateChanged?.Invoke(true);
                    
                    return (true, null);
                }
            }
            else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized)
            {
                Console.WriteLine("❌ User not found in DiunaBI database");
                return (false, "User does not exist in DiunaBI database.");
            }
            else
            {
                Console.WriteLine($"❌ Backend error: {response.StatusCode}");
                return (false, "DiunaBI server error. Please try again.");
            }

            return (false, "Unexpected error.");
        }
        catch (HttpRequestException ex)
        {
            Console.WriteLine($"❌ Network error: {ex.Message}");
            return (false, "Cannot connect to DiunaBI server.");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"❌ Validation error: {ex.Message}");
            return (false, "User verification error.");
        }
    }
    
    public async Task<bool> CheckAuthenticationAsync()
    {
        try
        {
            Console.WriteLine("=== AuthService.CheckAuthenticationAsync START ===");
            
            var token = await _jsRuntime.InvokeAsync<string?>("localStorage.getItem", "api_token");
            var userInfoJson = await _jsRuntime.InvokeAsync<string?>("localStorage.getItem", "user_info");
            
            _isAuthenticated = !string.IsNullOrEmpty(token);

            if (_isAuthenticated.Value && !string.IsNullOrEmpty(userInfoJson))
            {
                _apiToken = token;
                _userInfo = JsonSerializer.Deserialize<UserInfo>(userInfoJson);

                // Restore header
                _httpClient.DefaultRequestHeaders.Authorization =
                    new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _apiToken);
                
                Console.WriteLine($"✅ Session restored: {_userInfo?.Email}");
            }
            else
            {
                Console.WriteLine("❌ No valid session");
            }
            
            Console.WriteLine($"=== AuthService.CheckAuthenticationAsync END (authenticated={_isAuthenticated}) ===");
            
            return _isAuthenticated.Value;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"❌ CheckAuthentication ERROR: {ex.Message}");
            _isAuthenticated = false;
            _userInfo = null;
            return false;
        }
    }
    
    public async Task ClearAuthenticationAsync()
    {
        try
        {
            Console.WriteLine("=== AuthService.ClearAuthenticationAsync ===");
            await _jsRuntime.InvokeVoidAsync("localStorage.removeItem", "api_token");
            await _jsRuntime.InvokeVoidAsync("localStorage.removeItem", "user_info");
            
            _apiToken = null;
            _isAuthenticated = false;
            _userInfo = null;
            
            _httpClient.DefaultRequestHeaders.Authorization = null;
            
            Console.WriteLine("✅ Authentication cleared");
            AuthenticationStateChanged?.Invoke(false);
        }
        catch (Exception ex)
        {
            Console.WriteLine($"❌ ClearAuthentication ERROR: {ex.Message}");
        }
    }
    
    public async Task<string?> GetTokenAsync()
    {
        if (_isAuthenticated != true) 
        {
            await CheckAuthenticationAsync();
        }
        
        return _apiToken;
    }
    
    private class ApiTokenResponse
    {
        public string Token { get; set; } = string.Empty;
        public Guid Id { get; set; }
        public DateTime ExpirationTime { get; set; }
    }
}