using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Logging;
using MktZaloService.Domain.AggregatesModel.ChatbotRuleAggregate;
using System.Text.Json;

namespace MktZaloService.Infrastructure.Caching;

/// <summary>
/// EN: Interface for chatbot rules caching.
/// VI: Interface cho caching quy tắc chatbot.
/// </summary>
public interface IChatbotRuleCacheService
{
    /// <summary>
    /// EN: Get active rules from cache or load from database.
    /// VI: Lấy quy tắc đang hoạt động từ cache hoặc load từ database.
    /// </summary>
    Task<List<ChatbotRule>> GetActiveRulesAsync(
        Func<Task<List<ChatbotRule>>> loadFromDb,
        CancellationToken ct = default);

    /// <summary>
    /// EN: Invalidate rules cache (call after rule changes).
    /// VI: Xóa cache quy tắc (gọi sau khi thay đổi quy tắc).
    /// </summary>
    Task InvalidateRulesCacheAsync(CancellationToken ct = default);
}

/// <summary>
/// EN: Redis-based implementation of chatbot rules cache.
/// VI: Implementation cache quy tắc chatbot dựa trên Redis.
/// </summary>
public class ChatbotRuleCacheService : IChatbotRuleCacheService
{
    private const string ActiveRulesKey = "chatbot:rules:active";
    private static readonly TimeSpan CacheExpiration = TimeSpan.FromMinutes(5);

    private readonly IDistributedCache _cache;
    private readonly ILogger<ChatbotRuleCacheService> _logger;

    private static readonly JsonSerializerOptions JsonOptions = new()
    {
        PropertyNamingPolicy = JsonNamingPolicy.CamelCase
    };

    public ChatbotRuleCacheService(
        IDistributedCache cache,
        ILogger<ChatbotRuleCacheService> logger)
    {
        _cache = cache ?? throw new ArgumentNullException(nameof(cache));
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    /// <summary>
    /// EN: Get active rules from cache or load from database.
    /// VI: Lấy quy tắc đang hoạt động từ cache hoặc load từ database.
    /// </summary>
    public async Task<List<ChatbotRule>> GetActiveRulesAsync(
        Func<Task<List<ChatbotRule>>> loadFromDb,
        CancellationToken ct = default)
    {
        try
        {
            // EN: Try to get from cache first - but since ChatbotRule is complex with navigation properties,
            // we can't easily serialize/deserialize it. So we just cache a "version" and always load from DB
            // but skip if version hasn't changed. For now, just load from DB with short cache.
            // VI: Thử lấy từ cache trước - nhưng ChatbotRule phức tạp với navigation properties,
            // không thể dễ dàng serialize/deserialize. Tạm thời luôn load từ DB.

            // For MVP, just load from database
            // In production, consider caching rule IDs and loading fresh each time
            return await loadFromDb();
        }
        catch (Exception ex)
        {
            _logger.LogWarning(ex,
                "EN: Failed to get rules from cache, loading from DB. VI: Không thể lấy từ cache, đang load từ DB");
            return await loadFromDb();
        }
    }

    /// <summary>
    /// EN: Invalidate rules cache (call after rule changes).
    /// VI: Xóa cache quy tắc (gọi sau khi thay đổi quy tắc).
    /// </summary>
    public async Task InvalidateRulesCacheAsync(CancellationToken ct = default)
    {
        try
        {
            await _cache.RemoveAsync(ActiveRulesKey, ct);
            _logger.LogInformation("EN: Chatbot rules cache invalidated. VI: Đã xóa cache quy tắc chatbot");
        }
        catch (Exception ex)
        {
            _logger.LogWarning(ex,
                "EN: Failed to invalidate rules cache. VI: Không thể xóa cache quy tắc");
        }
    }
}
