using CMSMicroservice.Application.Common.Exceptions;
using CMSMicroservice.Application.Common.Interfaces;
using CMSMicroservice.Application.Common.Models;
using CMSMicroservice.Domain.Entities;
using CMSMicroservice.Domain.Entities.Club;
using CMSMicroservice.Domain.Entities.History;
using CMSMicroservice.Domain.Enums;
using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

namespace CMSMicroservice.Application.ClubMembershipCQ.Commands.ActivateClubMembership;

public class ActivateClubMembershipCommandHandler : IRequestHandler<ActivateClubMembershipCommand, bool>
{
    private readonly IApplicationDbContext _context;
    private readonly ICurrentUserService _currentUser;
    private readonly ILogger<ActivateClubMembershipCommandHandler> _logger;

    public ActivateClubMembershipCommandHandler(
        IApplicationDbContext context,
        ICurrentUserService currentUser,
        ILogger<ActivateClubMembershipCommandHandler> logger)
    {
        _context = context;
        _currentUser = currentUser;
        _logger = logger;
    }

    public async Task<bool> Handle(
        ActivateClubMembershipCommand request, 
        CancellationToken cancellationToken)
    {
        try
        {
            _logger.LogInformation(
                "Activating club membership for UserId: {UserId}",
                request.UserId
            );

            // 1. بررسی کاربر
            var user = await _context.Users
                .FirstOrDefaultAsync(u => u.Id == request.UserId, cancellationToken);

            if (user == null)
            {
                _logger.LogWarning("User not found: {UserId}", request.UserId);
                throw new NotFoundException(nameof(User), request.UserId);
            }

            // 2. بررسی اینکه پکیج خریده باشد
            if (user.PackagePurchaseMethod == PackagePurchaseMethod.None)
            {
                _logger.LogWarning(
                    "User {UserId} has not purchased golden package yet",
                    request.UserId
                );
                throw new BadRequestException(
                    "برای فعالسازی باشگاه مشتریان ابتدا باید پکیج طلایی خریداری کنید"
                );
            }

            // 3. بررسی موجودی کیف پول
            var wallet = await _context.UserWallets
                .FirstOrDefaultAsync(w => w.UserId == user.Id, cancellationToken);

            if (wallet == null)
            {
                _logger.LogError("Wallet not found for UserId: {UserId}", request.UserId);
                throw new NotFoundException("کیف پول کاربر یافت نشد");
            }

            if (wallet.Balance < 56_000_000)
            {
                _logger.LogWarning(
                    "User {UserId} has insufficient balance: {Balance}",
                    request.UserId,
                    wallet.Balance
                );
                throw new BadRequestException(
                    "برای فعالسازی باشگاه مشتریان باید حداقل 56 میلیون تومان موجودی اصلی داشته باشید"
                );
            }

            // 4. پیدا کردن UserOrder با PackageId
            var packageOrder = await _context.UserOrders
                .Include(o => o.Transaction)
                .Where(o =>
                    o.UserId == user.Id &&
                    o.PackageId != null &&
                    o.PaymentStatus == PaymentStatus.Success)
                .OrderByDescending(o => o.Created)
                .FirstOrDefaultAsync(cancellationToken);

            if (packageOrder == null)
            {
                _logger.LogWarning(
                    "No successful package order found for UserId: {UserId}",
                    request.UserId
                );
                throw new NotFoundException("سفارش پکیج طلایی یافت نشد");
            }

            // 5. بررسی Transaction
            if (packageOrder.Transaction == null)
            {
                _logger.LogError(
                    "Transaction not found for OrderId: {OrderId}",
                    packageOrder.Id
                );
                throw new NotFoundException("تراکنش مربوط به سفارش یافت نشد");
            }

            var transaction = packageOrder.Transaction;

            if (transaction.Type != TransactionType.DepositIpg &&
                transaction.Type != TransactionType.DepositExternal1)
            {
                _logger.LogWarning(
                    "Invalid transaction type for OrderId {OrderId}: {Type}",
                    packageOrder.Id,
                    transaction.Type
                );
                throw new BadRequestException(
                    "تراکنش معتبر برای فعالسازی باشگاه یافت نشد"
                );
            }

            // 6. بررسی عضویت فعلی
            var existingMembership = await _context.ClubMemberships
                .FirstOrDefaultAsync(c => c.UserId == user.Id, cancellationToken);

            // 6.1. دریافت مبلغ هدیه از تنظیمات
            var giftValueConfig = await _context.SystemConfigurations
                .FirstOrDefaultAsync(
                    c => c.Key == "Club.MembershipGiftValue" && c.IsActive,
                    cancellationToken
                );
            
            long giftValue = 25_200_000; // مقدار پیش‌فرض
            if (giftValueConfig != null && long.TryParse(giftValueConfig.Value, out var configValue))
            {
                giftValue = configValue;
                _logger.LogInformation(
                    "Using Club.MembershipGiftValue from configuration: {GiftValue}",
                    giftValue
                );
            }
            else
            {
                _logger.LogWarning(
                    "Club.MembershipGiftValue not found in configuration, using default: {GiftValue}",
                    giftValue
                );
            }

            ClubMembership entity;
            bool isNewMembership = existingMembership == null;
            var activationDate = DateTime.UtcNow;

            if (isNewMembership)
            {
                // ایجاد عضویت جدید
                entity = new ClubMembership
                {
                    UserId = user.Id,
                    IsActive = true,
                    ActivatedAt = activationDate,
                    InitialContribution = 56_000_000,
                    GiftValue = giftValue, // مقدار از تنظیمات
                    TotalEarned = 0,
                    PurchaseMethod = user.PackagePurchaseMethod
                };

                _context.ClubMemberships.Add(entity);
                
                _logger.LogInformation(
                    "Created new club membership for UserId {UserId} via {Method}, GiftValue: {GiftValue}",
                    user.Id,
                    user.PackagePurchaseMethod,
                    giftValue
                );
            }
            else
            {
                if (existingMembership.IsActive)
                {
                    _logger.LogInformation(
                        "User {UserId} is already an active club member",
                        user.Id
                    );
                    return true;
                }

                // فعال‌سازی مجدد
                entity = existingMembership;
                entity.IsActive = true;
                entity.ActivatedAt = activationDate;
                entity.PurchaseMethod = user.PackagePurchaseMethod;

                _context.ClubMemberships.Update(entity);
                
                _logger.LogInformation(
                    "Reactivated club membership for UserId {UserId}",
                    user.Id
                );
            }

            await _context.SaveChangesAsync(cancellationToken);

            // 7. ثبت تاریخچه
            var history = new ClubMembershipHistory
            {
                ClubMembershipId = entity.Id,
                UserId = entity.UserId,
                OldIsActive = !isNewMembership && !existingMembership!.IsActive,
                NewIsActive = true,
                Action = ClubMembershipAction.Activated,
                Reason = isNewMembership
                    ? $"Initial activation via {user.PackagePurchaseMethod}"
                    : $"Reactivated via {user.PackagePurchaseMethod}",
                PerformedBy = _currentUser.GetPerformedBy()
            };

            _context.ClubMembershipHistories.Add(history);
            await _context.SaveChangesAsync(cancellationToken);

            _logger.LogInformation(
                "Club membership activated successfully. UserId: {UserId}, MembershipId: {MembershipId}",
                user.Id,
                entity.Id
            );

            return true;
        }
        catch (Exception ex)
        {
            _logger.LogError(
                ex,
                "Error in ActivateClubMembershipCommand for UserId: {UserId}",
                request.UserId
            );
            throw;
        }
    }
}
