using MediatR;
using MktXService.Domain.AggregatesModel.ContactAggregate;

namespace MktXService.API.Application.Commands;

/// <summary>
/// EN: Handler for CreateContactCommand.
/// VI: Handler cho CreateContactCommand.
/// </summary>
public class CreateContactCommandHandler : IRequestHandler<CreateContactCommand, CreateContactResult>
{
    private readonly IContactRepository _contactRepository;
    private readonly ILogger<CreateContactCommandHandler> _logger;

    public CreateContactCommandHandler(
        IContactRepository contactRepository,
        ILogger<CreateContactCommandHandler> logger)
    {
        _contactRepository = contactRepository;
        _logger = logger;
    }

    public async Task<CreateContactResult> Handle(CreateContactCommand request, CancellationToken cancellationToken)
    {
        try
        {
            // EN: Check if contact already exists
            // VI: Kiểm tra liên hệ đã tồn tại chưa
            var existing = await _contactRepository.GetByTwitterUserIdAsync(request.AccountId, request.TwitterUserId);
            if (existing != null)
                return new CreateContactResult(false, null, "Contact already exists");

            var contact = new Contact(
                request.AccountId,
                request.TwitterUserId,
                request.Username,
                request.Source,
                request.DisplayName,
                request.ProfileImageUrl);

            // EN: Add tags if provided
            // VI: Thêm tags nếu có
            if (request.Tags != null)
            {
                foreach (var tag in request.Tags)
                    contact.AddTag(tag);
            }

            // EN: Add attributes if provided
            // VI: Thêm thuộc tính nếu có
            if (request.Attributes != null)
                contact.UpdateAttributes(request.Attributes);

            _contactRepository.Add(contact);
            await _contactRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);

            _logger.LogInformation("Contact {ContactId} created", contact.Id);
            return new CreateContactResult(true, contact.Id, null);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to create contact");
            return new CreateContactResult(false, null, ex.Message);
        }
    }
}

/// <summary>
/// EN: Handler for UpdateContactCommand.
/// VI: Handler cho UpdateContactCommand.
/// </summary>
public class UpdateContactCommandHandler : IRequestHandler<UpdateContactCommand, bool>
{
    private readonly IContactRepository _contactRepository;

    public UpdateContactCommandHandler(IContactRepository contactRepository)
    {
        _contactRepository = contactRepository;
    }

    public async Task<bool> Handle(UpdateContactCommand request, CancellationToken cancellationToken)
    {
        var contact = await _contactRepository.GetByIdAsync(request.ContactId);
        if (contact == null) return false;

        contact.UpdateProfile(request.Username, request.DisplayName, request.ProfileImageUrl);
        await _contactRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);
        return true;
    }
}

/// <summary>
/// EN: Handler for AddContactTagCommand.
/// VI: Handler cho AddContactTagCommand.
/// </summary>
public class AddContactTagCommandHandler : IRequestHandler<AddContactTagCommand, bool>
{
    private readonly IContactRepository _contactRepository;

    public AddContactTagCommandHandler(IContactRepository contactRepository)
    {
        _contactRepository = contactRepository;
    }

    public async Task<bool> Handle(AddContactTagCommand request, CancellationToken cancellationToken)
    {
        var contact = await _contactRepository.GetByIdAsync(request.ContactId);
        if (contact == null) return false;

        contact.AddTag(request.TagName);
        await _contactRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);
        return true;
    }
}

/// <summary>
/// EN: Handler for RemoveContactTagCommand.
/// VI: Handler cho RemoveContactTagCommand.
/// </summary>
public class RemoveContactTagCommandHandler : IRequestHandler<RemoveContactTagCommand, bool>
{
    private readonly IContactRepository _contactRepository;

    public RemoveContactTagCommandHandler(IContactRepository contactRepository)
    {
        _contactRepository = contactRepository;
    }

    public async Task<bool> Handle(RemoveContactTagCommand request, CancellationToken cancellationToken)
    {
        var contact = await _contactRepository.GetByIdAsync(request.ContactId);
        if (contact == null) return false;

        contact.RemoveTag(request.TagName);
        await _contactRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);
        return true;
    }
}

/// <summary>
/// EN: Handler for UpdateContactAttributesCommand.
/// VI: Handler cho UpdateContactAttributesCommand.
/// </summary>
public class UpdateContactAttributesCommandHandler : IRequestHandler<UpdateContactAttributesCommand, bool>
{
    private readonly IContactRepository _contactRepository;

    public UpdateContactAttributesCommandHandler(IContactRepository contactRepository)
    {
        _contactRepository = contactRepository;
    }

    public async Task<bool> Handle(UpdateContactAttributesCommand request, CancellationToken cancellationToken)
    {
        var contact = await _contactRepository.GetByIdAsync(request.ContactId);
        if (contact == null) return false;

        contact.UpdateAttributes(request.Attributes);
        await _contactRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);
        return true;
    }
}
