using CMSMicroservice.Application.Common.Interfaces;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using CMSMicroservice.Domain.Entities;

namespace CMSMicroservice.Application.UserCQ.Commands.AcceptContract;
public class AcceptContractCommandHandler : IRequestHandler<AcceptContractCommand, AcceptContractResponseDto>
{
    private readonly IApplicationDbContext _context;
    private readonly ICurrentUserService _currentUserService;
    private readonly IHashService _hashService;
    private readonly IGenerateJwtToken _generateJwt;
    private readonly IConfiguration _cfg;

    public AcceptContractCommandHandler(IApplicationDbContext context, ICurrentUserService currentUserService,
        IHashService hashService, IGenerateJwtToken generateJwt, IConfiguration cfg)
    {
        _context = context;
        _currentUserService = currentUserService;
        _hashService = hashService;
        _generateJwt = generateJwt;
        _cfg = cfg;
    }

    public async Task<AcceptContractResponseDto> Handle(AcceptContractCommand request, CancellationToken cancellationToken)
    {
        // پیدا کردن کاربر بر اساس UserId از توکن JWT
        if (!long.TryParse(_currentUserService.UserId, out var userId))
            return new AcceptContractResponseDto { IsSuccess = false, Message = "کاربر احراز هویت نشده است" };

        var user = await _context.Users
            .Include(u => u.UserContracts)
                .ThenInclude(uc => uc.Contract)
            .Include(u => u.UserRoles)
                .ThenInclude(ur => ur.Role)
            .Include(u => u.ClubMembership)
            .Where(x => x.Id == userId)
            .FirstOrDefaultAsync(cancellationToken);

        if (user == null)
            return new AcceptContractResponseDto { IsSuccess = false, Message = "کاربر یافت نشد" };

        // جستجوی OTP بر اساس شماره موبایل کاربر (نه Username)
        var otpToken = await _context.OtpTokens
            .Where(x => x.Mobile == user.Mobile && x.Purpose == "signContract" && !x.IsUsed)
            .OrderByDescending(x => x.Id)
            .FirstOrDefaultAsync(cancellationToken);

        var secret = _cfg["Otp:Secret"] ?? throw new InvalidOperationException("Otp:Secret not set");
        if (otpToken == null || !otpToken.IsValid() || !_hashService.VerifyHmacSha256Hex(request.Code, otpToken.CodeHash, secret))
            return new AcceptContractResponseDto { IsSuccess = false, Message = "کد تایید نامعتبر است" };

        // Create user contract
        var userContract = new UserContract
        {
            UserId = user.Id,
            ContractId = 1, // Default contract
            SignGuid = request.SignGuid,
            SignedPdfFile = request.ContractHtml
        };

        _context.UserContracts.Add(userContract);
        
        // Mark OTP as used
        otpToken.IsUsed = true;
        
        await _context.SaveChangesAsync(cancellationToken);

        // بارگذاری مجدد کاربر با تمام روابط برای تولید JWT صحیح
        user = await _context.Users
            .Include(u => u.UserContracts)
                .ThenInclude(uc => uc.Contract)
            .Include(u => u.UserRoles)
                .ThenInclude(ur => ur.Role)
            .Include(u => u.ClubMembership)
            .Where(x => x.Id == userId)
            .FirstAsync(cancellationToken);

        // Generate JWT token with updated contract status
        var token = await _generateJwt.GenerateJwtToken(user);

        return new AcceptContractResponseDto 
        { 
            IsSuccess = true, 
            Message = "قرارداد با موفقیت تایید شد",
            Token = token
        };
    }
}
