using System.Text.Json;
using MediatR;
using MembershipService.Domain.AggregatesModel.MemberAggregate;

namespace MembershipService.API.Application.Commands;

/// <summary>
/// EN: Handler for creating a new member.
/// VI: Handler để tạo member mới.
/// </summary>
public class CreateMemberCommandHandler : IRequestHandler<CreateMemberCommand, CreateMemberResult>
{
    private readonly IMemberRepository _memberRepository;
    private readonly ILogger<CreateMemberCommandHandler> _logger;

    public CreateMemberCommandHandler(
        IMemberRepository memberRepository,
        ILogger<CreateMemberCommandHandler> logger)
    {
        _memberRepository = memberRepository ?? throw new ArgumentNullException(nameof(memberRepository));
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    public async Task<CreateMemberResult> Handle(CreateMemberCommand request, CancellationToken cancellationToken)
    {
        // EN: Check if member already exists for this user
        // VI: Kiểm tra member đã tồn tại cho user này chưa
        var exists = await _memberRepository.ExistsForUserAsync(request.UserId, cancellationToken);
        if (exists)
        {
            throw new InvalidOperationException($"Member already exists for user {request.UserId}");
        }

        // EN: Create new member with gender (starts at level 1, exp 0)
        // VI: Tạo member mới với gender (bắt đầu ở level 1, exp 0)
        var member = new Member(request.UserId, request.CountryCode, request.Gender);

        // EN: Store name/phone in preferences JSON if provided
        // VI: Lưu name/phone vào preferences JSON nếu có
        if (!string.IsNullOrWhiteSpace(request.Name) || !string.IsNullOrWhiteSpace(request.Phone))
        {
            var prefs = new Dictionary<string, string>();
            if (!string.IsNullOrWhiteSpace(request.Name)) prefs["name"] = request.Name;
            if (!string.IsNullOrWhiteSpace(request.Phone)) prefs["phone"] = request.Phone;
            member.UpdatePreferences(JsonSerializer.Serialize(prefs));
        }

        _memberRepository.Add(member);
        await _memberRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);

        _logger.LogInformation("Created member {MemberId} for user {UserId} at level {Level}", 
            member.Id, request.UserId, member.CurrentLevel);

        return new CreateMemberResult
        {
            MemberId = member.Id,
            UserId = member.UserId,
            CurrentLevel = member.CurrentLevel,
            CreatedAt = member.CreatedAt
        };
    }
}
