using FluentResults;
using Microsoft.JSInterop;
using NexusReader.Application.Abstractions.Services;

namespace NexusReader.Web.Services;

/// <summary>
/// Server-side implementation of INativeStorageService.
/// Note: In Blazor Server, localStorage is only accessible via JS Interop.
/// This implementation handles cases where JS Interop might not be available (e.g. during prerendering).
/// </summary>
public class NativeStorageService : INativeStorageService
{
    private readonly IJSRuntime _jsRuntime;

    public NativeStorageService(IJSRuntime jsRuntime)
    {
        _jsRuntime = jsRuntime;
    }

    public async Task<Result> SaveStringAsync(string key, string value)
    {
        try
        {
            await _jsRuntime.InvokeVoidAsync("localStorage.setItem", key, value);
            return Result.Ok();
        }
        catch (Exception ex)
        {
            return Result.Fail(ex.Message);
        }
    }

    public async Task<Result<string?>> GetStringAsync(string key)
    {
        try
        {
            var value = await _jsRuntime.InvokeAsync<string?>("localStorage.getItem", key);
            return Result.Ok(value);
        }
        catch (Exception ex)
        {
            return Result.Fail(ex.Message);
        }
    }

    public Task<Result> SaveBoolAsync(string key, bool value) => SaveStringAsync(key, value.ToString());

    public async Task<Result<bool>> GetBoolAsync(string key, bool defaultValue = false)
    {
        try
        {
            var value = await _jsRuntime.InvokeAsync<string?>("localStorage.getItem", key);
            if (string.IsNullOrEmpty(value)) return Result.Ok(defaultValue);
            return Result.Ok(bool.TryParse(value, out var result) ? result : defaultValue);
        }
        catch
        {
            return Result.Ok(defaultValue);
        }
    }

    public async Task<Result> RemoveAsync(string key)
    {
        try
        {
            await _jsRuntime.InvokeVoidAsync("localStorage.removeItem", key);
            return Result.Ok();
        }
        catch (Exception ex)
        {
            return Result.Fail(ex.Message);
        }
    }

    public async Task<Result> SaveSecureString(string key, string value) => await SaveStringAsync(key, value);

    public async Task<Result<string?>> GetSecureString(string key) => await GetStringAsync(key);

    public Task<Result> RemoveSecureAsync(string key) => RemoveAsync(key);
}
