using CMSMicroservice.Protobuf.Protos.AppVersion;
using Blazored.LocalStorage;
using Microsoft.JSInterop;

namespace FrontOffice.Main.Utilities;

/// <summary>
/// نتیجه بررسی نسخه اپلیکیشن
/// </summary>
public class VersionCheckResult
{
    /// <summary>
    /// آیا نسخه جدیدی وجود دارد
    /// </summary>
    public bool HasNewVersion { get; set; }
    
    /// <summary>
    /// آیا آپدیت اجباری است (force update)
    /// </summary>
    public bool IsForceUpdate { get; set; }
    
    /// <summary>
    /// نسخه فعلی (local)
    /// </summary>
    public string? OldVersion { get; set; }
    
    /// <summary>
    /// نسخه جدید (server)
    /// </summary>
    public string? NewVersion { get; set; }
    
    /// <summary>
    /// یادداشت‌های انتشار
    /// </summary>
    public string? ReleaseNotes { get; set; }
    
    /// <summary>
    /// پیام آپدیت
    /// </summary>
    public string? UpdateMessage { get; set; }
    
    /// <summary>
    /// آیا کش باید پاک شود
    /// </summary>
    public bool RequiresCacheClear { get; set; }
}

/// <summary>
/// سرویس مدیریت نسخه اپلیکیشن و کش
/// وقتی نسخه جدید منتشر بشه، این سرویس متوجه میشه و کش رو پاک می‌کنه
/// </summary>
public class AppVersionService
{
    private readonly AppVersionContract.AppVersionContractClient _client;
    private readonly ILocalStorageService _localStorage;
    private readonly IJSRuntime _jsRuntime;
    private readonly ILogger<AppVersionService> _logger;
    
    private const string APP_NAME = "KaraBazarApp";
    private const string LOCAL_VERSION_KEY = "app_version";
    private const string LAST_CHECK_KEY = "app_version_last_check";
    private const string SKIPPED_VERSION_KEY = "app_version_skipped";
    private const string LAST_DIALOG_SHOWN_KEY = "app_version_last_dialog_shown";
    
    public AppVersionService(
        AppVersionContract.AppVersionContractClient client,
        ILocalStorageService localStorage,
        IJSRuntime jsRuntime,
        ILogger<AppVersionService> logger)
    {
        _client = client;
        _localStorage = localStorage;
        _jsRuntime = jsRuntime;
        _logger = logger;
    }

    /// <summary>
    /// بررسی نسخه اپلیکیشن و برگرداندن نتیجه
    /// </summary>
    /// <param name="ignoreSkipped">اگر true باشه، نسخه‌های skip شده هم نشون داده میشن (برای آیکون منو)</param>
    /// <param name="forDialog">اگر true باشه، چک میکنه که یک روز از آخرین نمایش گذشته (برای popup)</param>
    public async Task<VersionCheckResult> CheckVersionAsync(bool ignoreSkipped = false, bool forDialog = false)
    {
        var result = new VersionCheckResult();
        
        try
        {
            // دریافت نسخه فعلی از localStorage
            var localVersion = await _localStorage.GetItemAsStringAsync(LOCAL_VERSION_KEY);
            var skippedVersion = await _localStorage.GetItemAsStringAsync(SKIPPED_VERSION_KEY);
            var lastDialogShown = await _localStorage.GetItemAsStringAsync(LAST_DIALOG_SHOWN_KEY);
            
            result.OldVersion = localVersion;
            
            // بررسی نسخه از سرور
            var response = await _client.GetAppVersionAsync(new GetAppVersionRequest
            {
                AppName = APP_NAME,
                CurrentClientVersion = localVersion
            });

            if (!response.Found)
            {
                _logger.LogWarning("App version not found on server for {AppName}", APP_NAME);
                return result;
            }

            var serverVersion = response.CurrentVersion;
            result.NewVersion = serverVersion;
            result.ReleaseNotes = response.ReleaseNotes;
            result.UpdateMessage = response.UpdateMessage;
            result.RequiresCacheClear = response.RequiresFullCacheClear;
            result.IsForceUpdate = response.RequiresUpdate; // اگر نسخه کمتر از حداقل باشه
            
            // آیا نسخه جدید داریم؟
            if (localVersion != serverVersion)
            {
                result.HasNewVersion = true;
                
                // اگر این نسخه رو قبلاً skip کرده و force نیست
                if (!result.IsForceUpdate && skippedVersion == serverVersion && !ignoreSkipped)
                {
                    // برای popup: چک کن یک روز گذشته یا نه
                    if (forDialog)
                    {
                        var oneDayPassed = await HasOneDayPassedSinceLastDialogAsync(lastDialogShown);
                        if (!oneDayPassed)
                        {
                            result.HasNewVersion = false;
                        }
                        // اگه یک روز گذشته، HasNewVersion = true میمونه
                    }
                    else
                    {
                        result.HasNewVersion = false;
                    }
                }
                
                _logger.LogInformation(
                    "Version check: {OldVersion} -> {NewVersion}, Force: {Force}, Skipped: {Skipped}",
                    localVersion ?? "null", serverVersion, result.IsForceUpdate, skippedVersion);
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error checking app version");
        }
        
        return result;
    }

    /// <summary>
    /// چک کردن اینکه یک روز از آخرین نمایش دیالوگ گذشته یا نه
    /// </summary>
    private async Task<bool> HasOneDayPassedSinceLastDialogAsync(string? lastDialogShown)
    {
        if (string.IsNullOrEmpty(lastDialogShown))
            return true; // اگه هیچوقت نشون نداده، نشون بده
        
        if (DateTime.TryParse(lastDialogShown, out var lastShown))
        {
            return DateTime.UtcNow.Subtract(lastShown).TotalDays >= 1;
        }
        
        return true;
    }

    /// <summary>
    /// ثبت زمان نمایش دیالوگ
    /// </summary>
    public async Task RecordDialogShownAsync()
    {
        await _localStorage.SetItemAsStringAsync(LAST_DIALOG_SHOWN_KEY, DateTime.UtcNow.ToString("O"));
    }

    /// <summary>
    /// اعمال آپدیت - پاک کردن کش و ذخیره نسخه جدید
    /// </summary>
    public async Task ApplyUpdateAsync(string newVersion)
    {
        try
        {
            _logger.LogInformation("Applying update to version {Version}", newVersion);
            
            // پاک کردن کش
            await ClearAllCacheAsync();
            
            // ذخیره نسخه جدید
            await _localStorage.SetItemAsStringAsync(LOCAL_VERSION_KEY, newVersion);
            await _localStorage.SetItemAsStringAsync(LAST_CHECK_KEY, DateTime.UtcNow.ToString("O"));
            
            // پاک کردن نسخه skip شده
            await _localStorage.RemoveItemAsync(SKIPPED_VERSION_KEY);
            
            _logger.LogInformation("Update applied successfully to {Version}", newVersion);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error applying update");
            throw;
        }
    }

    /// <summary>
    /// Skip کردن این نسخه (بعداً)
    /// </summary>
    public async Task SkipVersionAsync(string version)
    {
        try
        {
            await _localStorage.SetItemAsStringAsync(SKIPPED_VERSION_KEY, version);
            _logger.LogInformation("Version {Version} skipped by user", version);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error skipping version");
        }
    }

    /// <summary>
    /// پاک کردن همه کش‌های اپلیکیشن
    /// </summary>
    private async Task ClearAllCacheAsync()
    {
        try
        {
            // پاک کردن کش مرورگر (Cache Storage و Service Worker)
            await _jsRuntime.InvokeVoidAsync("clearBrowserCache");
            
            _logger.LogInformation("Browser cache cleared successfully");
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error clearing browser cache");
        }
    }

    /// <summary>
    /// دریافت اطلاعات نسخه فعلی
    /// </summary>
    public async Task<AppVersionInfo?> GetCurrentVersionInfoAsync()
    {
        try
        {
            var response = await _client.GetAppVersionAsync(new GetAppVersionRequest
            {
                AppName = APP_NAME
            });

            if (!response.Found)
                return null;

            return new AppVersionInfo
            {
                CurrentVersion = response.CurrentVersion,
                MinRequiredVersion = response.MinRequiredVersion,
                RequiresUpdate = response.RequiresUpdate,
                UpdateMessage = response.UpdateMessage,
                ReleaseNotes = response.ReleaseNotes,
                LastUpdated = response.LastUpdated?.ToDateTime()
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error getting version info");
            return null;
        }
    }
}

public class AppVersionInfo
{
    public string CurrentVersion { get; set; } = string.Empty;
    public string MinRequiredVersion { get; set; } = string.Empty;
    public bool RequiresUpdate { get; set; }
    public string? UpdateMessage { get; set; }
    public string? ReleaseNotes { get; set; }
    public DateTime? LastUpdated { get; set; }
}
