using MediatR;
using MktXService.Domain.AggregatesModel.TemplateAggregate;

namespace MktXService.API.Application.Commands;

/// <summary>
/// EN: Handler for CreateTemplateCommand.
/// VI: Handler cho CreateTemplateCommand.
/// </summary>
public class CreateTemplateCommandHandler : IRequestHandler<CreateTemplateCommand, CreateTemplateResult>
{
    private readonly ITemplateRepository _templateRepository;
    private readonly ILogger<CreateTemplateCommandHandler> _logger;

    public CreateTemplateCommandHandler(
        ITemplateRepository templateRepository,
        ILogger<CreateTemplateCommandHandler> logger)
    {
        _templateRepository = templateRepository;
        _logger = logger;
    }

    public async Task<CreateTemplateResult> Handle(CreateTemplateCommand request, CancellationToken cancellationToken)
    {
        try
        {
            var template = new Template(
                request.MerchantId,
                request.Name,
                request.Type,
                request.Content);

            _templateRepository.Add(template);
            await _templateRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);

            _logger.LogInformation("Template {TemplateId} created", template.Id);
            return new CreateTemplateResult(true, template.Id, null);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to create template");
            return new CreateTemplateResult(false, null, ex.Message);
        }
    }
}

/// <summary>
/// EN: Handler for UpdateTemplateCommand.
/// VI: Handler cho UpdateTemplateCommand.
/// </summary>
public class UpdateTemplateCommandHandler : IRequestHandler<UpdateTemplateCommand, bool>
{
    private readonly ITemplateRepository _templateRepository;

    public UpdateTemplateCommandHandler(ITemplateRepository templateRepository)
    {
        _templateRepository = templateRepository;
    }

    public async Task<bool> Handle(UpdateTemplateCommand request, CancellationToken cancellationToken)
    {
        var template = await _templateRepository.GetByIdAsync(request.TemplateId);
        if (template == null) return false;

        template.Update(request.Name, request.Content);
        await _templateRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);
        return true;
    }
}

/// <summary>
/// EN: Handler for DeleteTemplateCommand.
/// VI: Handler cho DeleteTemplateCommand.
/// </summary>
public class DeleteTemplateCommandHandler : IRequestHandler<DeleteTemplateCommand, bool>
{
    private readonly ITemplateRepository _templateRepository;
    private readonly ILogger<DeleteTemplateCommandHandler> _logger;

    public DeleteTemplateCommandHandler(
        ITemplateRepository templateRepository,
        ILogger<DeleteTemplateCommandHandler> logger)
    {
        _templateRepository = templateRepository;
        _logger = logger;
    }

    public async Task<bool> Handle(DeleteTemplateCommand request, CancellationToken cancellationToken)
    {
        var template = await _templateRepository.GetByIdAsync(request.TemplateId);
        if (template == null) return false;

        _templateRepository.Delete(template);
        await _templateRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);

        _logger.LogInformation("Template {TemplateId} deleted", request.TemplateId);
        return true;
    }
}

/// <summary>
/// EN: Handler for PreviewTemplateCommand.
/// VI: Handler cho PreviewTemplateCommand.
/// </summary>
public class PreviewTemplateCommandHandler : IRequestHandler<PreviewTemplateCommand, PreviewTemplateResult>
{
    private readonly ITemplateRepository _templateRepository;

    public PreviewTemplateCommandHandler(ITemplateRepository templateRepository)
    {
        _templateRepository = templateRepository;
    }

    public async Task<PreviewTemplateResult> Handle(PreviewTemplateCommand request, CancellationToken cancellationToken)
    {
        try
        {
            var template = await _templateRepository.GetByIdAsync(request.TemplateId);
            if (template == null)
                return new PreviewTemplateResult(false, null, "Template not found");

            var rendered = template.Render(request.Variables);
            return new PreviewTemplateResult(true, rendered, null);
        }
        catch (Exception ex)
        {
            return new PreviewTemplateResult(false, null, ex.Message);
        }
    }
}
