using Microsoft.Extensions.Logging;
using MediatR;
using MktXService.Domain.AggregatesModel.ContactAggregate;
using MktXService.Domain.AggregatesModel.ConversationAggregate;
using MktXService.Domain.AggregatesModel.TwitterAccountAggregate;
using MktXService.Domain.Events;
using MktXService.Infrastructure.ExternalServices.OpenAI;
using Quartz;

namespace MktXService.Infrastructure.BackgroundJobs;

/// <summary>
/// EN: Background job for processing Twitter webhook events.
/// VI: Background job để xử lý các webhook events từ Twitter.
/// </summary>
/// <remarks>
/// EN: Processes incoming DMs, follows, and other Twitter events asynchronously.
/// VI: Xử lý các DM đến, follows, và các events Twitter khác một cách bất đồng bộ.
/// </remarks>
[DisallowConcurrentExecution]
public class WebhookEventProcessorJob : IJob
{
    private readonly ITwitterAccountRepository _accountRepository;
    private readonly IContactRepository _contactRepository;
    private readonly IConversationRepository _conversationRepository;
    private readonly IAIServiceClient _aiClient;
    private readonly IMediator _mediator;
    private readonly ILogger<WebhookEventProcessorJob> _logger;

    public WebhookEventProcessorJob(
        ITwitterAccountRepository accountRepository,
        IContactRepository contactRepository,
        IConversationRepository conversationRepository,
        IAIServiceClient aiClient,
        IMediator mediator,
        ILogger<WebhookEventProcessorJob> logger)
    {
        _accountRepository = accountRepository;
        _contactRepository = contactRepository;
        _conversationRepository = conversationRepository;
        _aiClient = aiClient;
        _mediator = mediator;
        _logger = logger;
    }

    public async Task Execute(IJobExecutionContext context)
    {
        _logger.LogDebug("WebhookEventProcessorJob started at {Time}", DateTimeOffset.UtcNow);

        // EN: In production, this would poll from a message queue (RabbitMQ/Redis)
        // VI: Trong production, sẽ poll từ message queue (RabbitMQ/Redis)
        var events = await GetPendingWebhookEventsAsync();

        foreach (var evt in events)
        {
            if (context.CancellationToken.IsCancellationRequested)
                break;

            try
            {
                await ProcessEventAsync(evt, context.CancellationToken);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to process webhook event {EventType}", evt.EventType);
            }
        }
    }

    private async Task<IEnumerable<WebhookEvent>> GetPendingWebhookEventsAsync()
    {
        // EN: Placeholder - In production, dequeue from message broker
        // VI: Placeholder - Trong production, dequeue từ message broker
        return await Task.FromResult(Enumerable.Empty<WebhookEvent>());
    }

    private async Task ProcessEventAsync(WebhookEvent evt, CancellationToken cancellationToken)
    {
        switch (evt.EventType)
        {
            case WebhookEventType.DirectMessageCreate:
                await ProcessDirectMessageAsync(evt, cancellationToken);
                break;
            case WebhookEventType.Follow:
                await ProcessFollowAsync(evt, cancellationToken);
                break;
            case WebhookEventType.Unfollow:
                await ProcessUnfollowAsync(evt, cancellationToken);
                break;
            default:
                _logger.LogDebug("Unhandled event type: {EventType}", evt.EventType);
                break;
        }
    }

    private async Task ProcessDirectMessageAsync(WebhookEvent evt, CancellationToken cancellationToken)
    {
        var data = evt.Data as DirectMessageEventData;
        if (data == null) return;

        _logger.LogInformation("Processing DM from {SenderId}", data.SenderId);

        // EN: Find or create contact
        // VI: Tìm hoặc tạo liên hệ
        var contact = await _contactRepository.GetByTwitterUserIdAsync(evt.AccountId, data.SenderId);
        if (contact == null)
        {
            contact = new Contact(
                evt.AccountId,
                data.SenderId,
                data.SenderUsername ?? "unknown",
                "dm", // source
                data.SenderName,
                null);
            _contactRepository.Add(contact);
        }

        // EN: Find or create conversation
        // VI: Tìm hoặc tạo hội thoại
        var conversation = await _conversationRepository.GetOpenByContactIdAsync(contact.Id);
        if (conversation == null)
        {
            conversation = new Conversation(contact.Id, evt.AccountId, "dm");
            _conversationRepository.Add(conversation);
        }

        // EN: Add the message
        // VI: Thêm tin nhắn
        var message = conversation.AddMessage(
            "inbound",
            "text",
            data.Text ?? "",
            false,
            data.MessageId);

        // EN: Detect intent if AI is enabled
        // VI: Phát hiện ý định nếu AI được bật
        if (!string.IsNullOrEmpty(data.Text))
        {
            var intentResult = await _aiClient.DetectIntentAsync(
                data.Text,
                new[] { "greeting", "question", "support", "order", "feedback", "other" },
                cancellationToken);

            _logger.LogInformation("Detected intent: {Intent} (confidence: {Confidence})",
                intentResult.Intent, intentResult.Confidence);

            // EN: Publish domain event for further processing
            // VI: Publish domain event để xử lý tiếp
            await _mediator.Publish(new MessageReceivedDomainEvent(message), cancellationToken);
        }

        await _conversationRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);
    }

    private async Task ProcessFollowAsync(WebhookEvent evt, CancellationToken cancellationToken)
    {
        var data = evt.Data as FollowEventData;
        if (data == null) return;

        _logger.LogInformation("New follower: {FollowerId}", data.FollowerId);

        // EN: Create contact for new follower
        // VI: Tạo liên hệ cho follower mới
        var existingContact = await _contactRepository.GetByTwitterUserIdAsync(evt.AccountId, data.FollowerId);
        if (existingContact == null)
        {
            var contact = new Contact(
                evt.AccountId,
                data.FollowerId,
                data.FollowerUsername ?? "unknown",
                "follow", // source
                data.FollowerName,
                null);
            contact.AddTag("follower");
            _contactRepository.Add(contact);

            await _contactRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);
        }
    }

    private async Task ProcessUnfollowAsync(WebhookEvent evt, CancellationToken cancellationToken)
    {
        var data = evt.Data as FollowEventData;
        if (data == null) return;

        _logger.LogInformation("Lost follower: {FollowerId}", data.FollowerId);

        var contact = await _contactRepository.GetByTwitterUserIdAsync(evt.AccountId, data.FollowerId);
        if (contact != null)
        {
            contact.RemoveTag("follower");
            contact.AddTag("unfollowed");
            await _contactRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);
        }
    }
}

#region Event DTOs

public enum WebhookEventType
{
    DirectMessageCreate,
    DirectMessageRead,
    Follow,
    Unfollow,
    Mention,
    Like
}

public class WebhookEvent
{
    public Guid AccountId { get; set; }
    public WebhookEventType EventType { get; set; }
    public object? Data { get; set; }
    public DateTime ReceivedAt { get; set; }
}

public class DirectMessageEventData
{
    public string MessageId { get; set; } = string.Empty;
    public string SenderId { get; set; } = string.Empty;
    public string? SenderUsername { get; set; }
    public string? SenderName { get; set; }
    public string? Text { get; set; }
    public List<string>? MediaUrls { get; set; }
}

public class FollowEventData
{
    public string FollowerId { get; set; } = string.Empty;
    public string? FollowerUsername { get; set; }
    public string? FollowerName { get; set; }
}

#endregion

/// <summary>
/// EN: Schedule configuration for WebhookEventProcessorJob.
/// VI: Cấu hình lịch trình cho WebhookEventProcessorJob.
/// </summary>
public static class WebhookEventProcessorJobSetup
{
    public static void ConfigureJob(IServiceCollectionQuartzConfigurator configurator)
    {
        var jobKey = new JobKey(nameof(WebhookEventProcessorJob));

        configurator.AddJob<WebhookEventProcessorJob>(opts => opts.WithIdentity(jobKey));

        configurator.AddTrigger(opts => opts
            .ForJob(jobKey)
            .WithIdentity($"{nameof(WebhookEventProcessorJob)}-trigger")
            .WithSimpleSchedule(x => x
                .WithIntervalInSeconds(5)
                .RepeatForever()));
    }
}
