using CMSMicroservice.Application.Common.Interfaces;
using MediatR;
using Microsoft.EntityFrameworkCore;

namespace CMSMicroservice.Application.UserAddressCQ.Commands.UpdateCustomerAddress;

public class UpdateCustomerAddressCommandHandler : IRequestHandler<UpdateCustomerAddressCommand, Unit>
{
    private readonly IApplicationDbContext _context;
    private readonly ICurrentUserService _currentUser;

    public UpdateCustomerAddressCommandHandler(IApplicationDbContext context, ICurrentUserService currentUser)
    {
        _context = context;
        _currentUser = currentUser;
    }

    public async Task<Unit> Handle(UpdateCustomerAddressCommand request, CancellationToken cancellationToken)
    {
        // Extract UserId from JWT token
        var userId = long.TryParse(_currentUser.UserId, out var id) ? id : 0;
        if (userId == 0)
        {
            throw new UnauthorizedAccessException("User not authenticated");
        }

        // Find address and verify ownership
        var address = await _context.UserAddresses
            .FirstOrDefaultAsync(ua => ua.Id == request.Id && ua.UserId == userId && !ua.IsDeleted, cancellationToken);

        if (address == null)
        {
            throw new Exception("آدرس یافت نشد یا به شما تعلق ندارد");
        }

        // If setting as default, unset other defaults
        if (request.IsDefault && !address.IsDefault)
        {
            var existingDefaults = await _context.UserAddresses
                .Where(ua => ua.UserId == userId && ua.IsDefault && ua.Id != request.Id && !ua.IsDeleted)
                .ToListAsync(cancellationToken);

            foreach (var addr in existingDefaults)
            {
                addr.IsDefault = false;
            }
        }

        // Update address
        address.Title = request.Title;
        address.Address = request.Address;
        address.PostalCode = request.PostalCode;
        address.IsDefault = request.IsDefault;
        address.CityId = request.CityId;
        address.LastModified = DateTime.UtcNow;

        _context.UserAddresses.Update(address);
        await _context.SaveChangesAsync(cancellationToken);

        return Unit.Value;
    }
}
