<?php

declare(strict_types=1);

namespace App\Http\Controllers\Wallet;

use App\Http\Controllers\Controller;
use App\Http\Requests\Wallet\WalletWithdrawRequest;
use App\Http\Resources\WithdrawalRequestResource;
use App\Models\BankCard;
use App\Models\WithdrawalRequest;
use App\Services\WalletService;
use App\Support\ApiResponse;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Gate;
use InvalidArgumentException;

class WithdrawalRequestController extends Controller
{
    public function index(Request $request)
    {
        Gate::authorize('viewAny', WithdrawalRequest::class);

        $query = WithdrawalRequest::query()
            ->with('bankCard')
            ->where('user_id', $request->user()->id)
            ->latest();

        if ($request->filled('status')) {
            $query->where('status', $request->string('status'));
        }

        $perPage = min($request->integer('per_page', 15), 50);

        return WithdrawalRequestResource::collection(
            $request->boolean('noPaginate') ? $query->get() : $query->paginate($perPage)
        );
    }

    public function show(Request $request, WithdrawalRequest $withdrawalRequest)
    {
        Gate::authorize('view', $withdrawalRequest);

        if ($withdrawalRequest->user_id !== $request->user()->id && ! $request->user()->hasRole('admin')) {
            return ApiResponse::forbidden('دسترسی مجاز نیست.');
        }

        return new WithdrawalRequestResource($withdrawalRequest->load('bankCard'));
    }

    public function store(WalletWithdrawRequest $request, WalletService $wallet)
    {
        Gate::authorize('create', WithdrawalRequest::class);

        $user = $request->user();
        $amount = $request->integer('amount');

        $card = null;
        if ($request->filled('bank_card_id')) {
            $card = BankCard::query()
                ->where('user_id', $user->id)
                ->where('id', $request->integer('bank_card_id'))
                ->where('status', BankCard::STATUS_ACTIVE)
                ->firstOrFail();
        }

        $shaba = $card?->shaba ?? (string) $request->string('shaba');
        $holder = $card?->account_holder_name ?? (string) $request->string('account_holder_name');

        try {
            DB::beginTransaction();

            $wallet->holdForWithdrawal(
                $user,
                $amount,
                'درخواست برداشت به شبا ' . $shaba,
                [
                    'shaba' => $shaba,
                    'bank_card_id' => $card?->id,
                ],
            );

            $withdrawal = WithdrawalRequest::create([
                'user_id' => $user->id,
                'bank_card_id' => $card?->id,
                'amount' => $amount,
                'shaba' => $shaba,
                'account_holder_name' => $holder,
                'wallet_balance_at_request' => $user->fresh()->wallet + $amount,
                'status' => WithdrawalRequest::STATUS_PENDING,
            ]);

            DB::commit();
        } catch (InvalidArgumentException $exception) {
            DB::rollBack();

            return ApiResponse::response(message: $exception->getMessage(), status: 422);
        } catch (Exception $exception) {
            DB::rollBack();

            return ApiResponse::response(message: $exception->getMessage(), status: 419);
        }

        return ApiResponse::created(
            new WithdrawalRequestResource($withdrawal->load('bankCard')),
            'درخواست برداشت ثبت شد.'
        );
    }
}
