using Application.Abstractions.Data;
using Application.Abstractions.Messaging;
using Application.Features.Api.Studio.Helpers;
using Microsoft.EntityFrameworkCore;
using SharedKernel.Results;

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

internal sealed class Handler(IAppDbContext db) : IQueryHandler<Query, Result<Response>>
{
    public async Task<Result<Response>> Handle(Query request, CancellationToken ct)
    {
        // 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;
            }
        }

        // 정산 계좌 목록
        var accounts = await db.SettlementAccount.AsNoTracking()
            .Where(a => a.MemberID == request.MemberID)
            .OrderBy(a => a.CreatedAt)
            .Select(a => new AccountInfo(
                a.ID,
                a.BankName,
                a.AccountNumber.Length > 4 ? "****" + a.AccountNumber.Substring(a.AccountNumber.Length - 4) : a.AccountNumber,
                a.AccountHolder
            ))
            .ToListAsync(ct);

        // 출금 내역
        var (start, end) = PeriodHelper.GetRange(request.Period);

        var baseQuery = db.WithdrawalRequest.AsNoTracking()
            .Where(w => w.MemberID == request.MemberID && w.RequestedAt >= start && w.RequestedAt <= end);

        var total = await baseQuery.CountAsync(ct);

        var list = await baseQuery
            .OrderByDescending(w => w.RequestedAt)
            .Skip((request.Page - 1) * request.PerPage)
            .Take(request.PerPage)
            .Select(w => new WithdrawItem(
                w.ID,
                w.RequestedAmount,
                w.WithholdingTax,
                w.NetAmount,
                w.Status.ToString(),
                w.BankName,
                w.AccountNumber.Length > 4 ? "****" + w.AccountNumber.Substring(w.AccountNumber.Length - 4) : w.AccountNumber,
                w.RequestedAt,
                w.ProcessedAt,
                w.RejectedReason
            ))
            .ToListAsync(ct);

        return Result.Success(new Response(total, withdrawableBalance, accounts, list));
    }
}