using MediatR;
using System.Text.Json;
using WhatsAppService.Domain.AggregatesModel.AutomationFlowAggregate;
using WhatsAppService.Domain.Events;

namespace WhatsAppService.API.BackgroundJobs;

/// <summary>
/// EN: Domain event handler for processing automation triggers on new messages.
/// VI: Domain event handler để xử lý automation triggers khi có tin nhắn mới.
/// </summary>
public class AutomationTriggerHandler : INotificationHandler<MessageReceivedEvent>
{
    private readonly IServiceProvider _serviceProvider;
    private readonly ILogger<AutomationTriggerHandler> _logger;

    public AutomationTriggerHandler(
        IServiceProvider serviceProvider,
        ILogger<AutomationTriggerHandler> logger)
    {
        _serviceProvider = serviceProvider;
        _logger = logger;
    }

    public async Task Handle(MessageReceivedEvent notification, CancellationToken cancellationToken)
    {
        try
        {
            using var scope = _serviceProvider.CreateScope();
            var flowRepository = scope.ServiceProvider.GetRequiredService<IAutomationFlowRepository>();

            // Get active keyword-triggered flows for this shop
            var flows = await flowRepository.GetByTriggerTypeAsync(
                notification.ShopId, 
                TriggerType.Keyword, 
                cancellationToken);

            if (flows.Count == 0)
            {
                return;
            }

            var messageText = notification.Content.Text?.Trim() ?? string.Empty;
            var hasMatchedFlow = false;

            foreach (var flow in flows.OrderByDescending(f => f.Priority))
            {
                if (!IsKeywordMatch(flow.TriggerConfig, messageText))
                {
                    continue;
                }

                hasMatchedFlow = true;
                flow.IncrementExecutionCount();
                flowRepository.Update(flow);

                _logger.LogInformation(
                    "Matched keyword automation flow {FlowId} for customer {CustomerWaId}.",
                    flow.Id,
                    notification.CustomerWaId);

                // If matched, execute flow steps
                // await ExecuteFlowAsync(flow, notification, cancellationToken);
            }

            if (hasMatchedFlow)
            {
                await flowRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error processing automation triggers for message {MessageId}", notification.MessageId);
        }
    }

    private static bool IsKeywordMatch(string triggerConfigJson, string messageText)
    {
        if (string.IsNullOrWhiteSpace(messageText) || string.IsNullOrWhiteSpace(triggerConfigJson))
        {
            return false;
        }

        try
        {
            using var doc = JsonDocument.Parse(triggerConfigJson);
            var root = doc.RootElement;

            var keywords = ExtractKeywords(root);
            if (keywords.Count == 0)
            {
                return false;
            }

            var normalizedMessage = messageText.Trim().ToLowerInvariant();
            var matchType = root.TryGetProperty("matchType", out var matchTypeElement)
                ? matchTypeElement.GetString()?.Trim().ToLowerInvariant()
                : "contains";

            return matchType switch
            {
                "exact" => keywords.Any(keyword => normalizedMessage.Equals(keyword, StringComparison.Ordinal)),
                _ => keywords.Any(keyword => normalizedMessage.Contains(keyword, StringComparison.Ordinal)),
            };
        }
        catch (JsonException)
        {
            return false;
        }
    }

    private static List<string> ExtractKeywords(JsonElement root)
    {
        var keywords = new List<string>();

        if (root.TryGetProperty("keyword", out var keywordElement) &&
            keywordElement.ValueKind == JsonValueKind.String)
        {
            var keyword = keywordElement.GetString()?.Trim().ToLowerInvariant();
            if (!string.IsNullOrWhiteSpace(keyword))
            {
                keywords.Add(keyword);
            }
        }

        if (root.TryGetProperty("keywords", out var keywordsElement) &&
            keywordsElement.ValueKind == JsonValueKind.Array)
        {
            foreach (var element in keywordsElement.EnumerateArray())
            {
                if (element.ValueKind != JsonValueKind.String)
                {
                    continue;
                }

                var keyword = element.GetString()?.Trim().ToLowerInvariant();
                if (!string.IsNullOrWhiteSpace(keyword))
                {
                    keywords.Add(keyword);
                }
            }
        }

        return keywords.Distinct(StringComparer.Ordinal).ToList();
    }
}
