using Application.Abstractions.Data;
using Application.Abstractions.Messaging;
using Domain.Entities.Donations.ValueObject;
using Microsoft.EntityFrameworkCore;
using SharedKernel.Results;

namespace Application.Features.Api.Studio.Wallet.GetBalance;

internal sealed class Handler(IAppDbContext db) : IQueryHandler<Query, Result<Response>>
{
    private static readonly Response Empty = new(0, 0, 0, 0, []);

    public async Task<Result<Response>> Handle(Query request, CancellationToken ct)
    {
        var channel = await db.Channel.AsNoTracking().FirstOrDefaultAsync(c => c.MemberID == request.MemberID && c.IsActive, ct);
        if (channel is null)
        {
            return Result.Success(Empty);
        }

        // Wallet Donation 잔액
        var wallet = await db.Wallet.AsNoTracking()
            .Include(w => w.Balances)
            .FirstOrDefaultAsync(w => w.MemberID == request.MemberID, ct);

        var withdrawableBalance = 0;
        if (wallet is not null)
        {
            var donationBal = wallet.Balances.FirstOrDefault(b => b.Type == Domain.Entities.Wallets.ValueObject.WalletBalanceType.Donation);
            if (donationBal is not null)
            {
                withdrawableBalance = (int)donationBal.Amount.Value;
            }
        }

        // 누적 수익 (Donation NetAmount 합계)
        var totalEarned = await db.Donation.AsNoTracking()
            .Where(d => d.ReceiverMemberID == request.MemberID && !d.IsTest)
            .SumAsync(d => d.NetAmount, ct);

        // 누적 출금 (완료된 출금 합계)
        var totalWithdrawn = await db.WithdrawalRequest.AsNoTracking()
            .Where(w => w.MemberID == request.MemberID && w.Status == WithdrawalStatus.Completed)
            .SumAsync(w => w.NetAmount, ct);

        // 대기 중 출금
        var pendingWithdrawal = await db.WithdrawalRequest.AsNoTracking()
            .Where(w => w.MemberID == request.MemberID && (w.Status == WithdrawalStatus.Pending || w.Status == WithdrawalStatus.Processing))
            .SumAsync(w => w.RequestedAmount, ct);

        // 최근 거래 내역 10건
        var recentTx = await db.WalletTransaction.AsNoTracking()
            .Where(t => t.Wallet!.MemberID == request.MemberID && t.BalanceType == Domain.Entities.Wallets.ValueObject.WalletBalanceType.Donation)
            .OrderByDescending(t => t.CreatedAt)
            .Take(10)
            .Select(t => new TransactionItem(
                t.ID,
                t.TxType.ToString(),
                (int)t.Amount.Value,
                (int)t.BalanceAfter.Value,
                t.Memo ?? "",
                t.CreatedAt
            ))
            .ToListAsync(ct);

        return Result.Success(new Response(
            withdrawableBalance,
            totalEarned,
            totalWithdrawn,
            pendingWithdrawal,
            recentTx
        ));
    }
}