<?php

declare(strict_types=1);

namespace App\Http\Controllers\Invoice;

use App\Http\Controllers\Controller;
use App\Http\Requests\Invoice\PayInvoiceRequest;
use App\Http\Resources\PaymentResource;
use App\Models\Invoice;
use App\Models\WalletTransaction;
use App\Services\PaymentService;
use App\Support\ApiResponse;
use Exception;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Gate;

class PayInvoiceController extends Controller
{
    public function __invoke(PayInvoiceRequest $request, Invoice $invoice, PaymentService $paymentService)
    {
        Gate::authorize('pay', $invoice);

        if ($invoice->status === Invoice::STATUS_PAID) {
            return ApiResponse::response(message: 'این فاکتور قبلاً پرداخت شده است.', status: 422);
        }

        if (! $invoice->isPayable()) {
            return ApiResponse::response(message: 'این فاکتور در وضعیت قابل پرداخت نیست.', status: 422);
        }

        app(\App\Services\InvoiceService::class)->refreshLateFee($invoice);
        $invoice->refresh();

        $amount = $invoice->payableAmount();
        if ($amount <= 0) {
            return ApiResponse::response(message: 'مبلغ فاکتور برای پرداخت معتبر نیست.', status: 422);
        }

        $user = $request->user();
        $method = (string) $request->input('payment_method', 'gateway');

        if ($method === 'wallet') {
            return $this->payWithWallet($request, $invoice, $user, $amount);
        }

        try {
            $gateway = (string) $request->input('gateway', config('payment.default', 'zibal'));

            $result = $paymentService->startGateway(
                $user,
                $amount,
                Invoice::class,
                (int) $invoice->id,
                $gateway,
                (string) ($invoice->number ?? $invoice->id),
                $invoice->project_id ? (int) $invoice->project_id : null,
            );
        } catch (Exception $exception) {
            return ApiResponse::response(message: $exception->getMessage(), status: 419);
        }

        return ApiResponse::response(
            data: [
                'invoice_id' => $invoice->id,
                'payment' => new PaymentResource($result['payment']->loadMissing('user')),
                'gateway_url' => $result['gateway_url'],
                'gateway' => $result['gateway'],
                'payment_method' => 'gateway',
            ],
            next: $result['gateway_url'],
            message: 'در حال انتقال به درگاه پرداخت.',
            status: 201,
        );
    }

    private function payWithWallet(PayInvoiceRequest $request, Invoice $invoice, $user, int $amount)
    {
        try {
            DB::beginTransaction();

            $walletAmount = $request->integer('wallet_amount', $amount);

            if ((int) $user->wallet < $walletAmount) {
                DB::rollBack();

                return ApiResponse::response(message: 'موجودی کیف پول کافی نیست.', status: 422);
            }

            $user->decrement('wallet', $walletAmount);

            WalletTransaction::create([
                'user_id' => $user->id,
                'type' => WalletTransaction::TYPE_PURCHASE,
                'amount' => $walletAmount,
                'balance_after' => $user->fresh()->wallet,
                'description' => 'پرداخت فاکتور ' . ($invoice->number ?? $invoice->id),
                'status' => WalletTransaction::STATUS_COMPLETED,
                'project_id' => $invoice->project_id,
                'invoice_id' => $invoice->id,
            ]);

            $invoice->update([
                'status' => Invoice::STATUS_PAID,
                'late_fee_amount' => 0,
            ]);

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

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

        return ApiResponse::success([
            'invoice_id' => $invoice->id,
            'status' => $invoice->status,
            'payment_method' => 'wallet',
            'gateway_url' => null,
        ], 'فاکتور با موفقیت از کیف پول پرداخت شد.');
    }
}
