<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Jobs\ProcessPayoutRequest;
use App\Models\Payout;
use App\Models\UserPaymentMethod;
use App\Models\Wallet;
use App\Models\WalletTransaction;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class WalletController extends Controller
{
    public function show(Request $request): JsonResponse
    {
        $user = $request->user();

        abort_unless($user->role === 'liner', 403);

        $wallet = Wallet::firstOrCreate(
            ['user_id' => $user->id],
            ['balance' => 0, 'currency' => 'EUR']
        );

        return response()->json(['data' => $wallet]);
    }

    public function history(Request $request): JsonResponse
    {
        $user = $request->user();

        abort_unless($user->role === 'liner', 403);

        $transactions = WalletTransaction::query()
            ->where('user_id', $user->id)
            ->latest()
            ->paginate(20);

        return response()->json(['data' => $transactions]);
    }

    public function withdraw(Request $request): JsonResponse
    {
        $user = $request->user();

        abort_unless($user->role === 'liner', 403);

        $data = $request->validate([
            'amount' => ['required', 'numeric', 'min:1'],
            'provider' => ['nullable', 'string', 'max:100'],
            'payment_method_id' => ['nullable', 'integer', 'exists:user_payment_methods,id'],
        ]);

        $wallet = Wallet::firstOrCreate(
            ['user_id' => $user->id],
            ['balance' => 0, 'currency' => 'EUR']
        );

        $amount = (float) $data['amount'];

        if ((float) $wallet->balance < $amount) {
            return response()->json(['message' => 'Solde insuffisant'], 422);
        }

        $paymentMethod = null;
        if (isset($data['payment_method_id'])) {
            $paymentMethod = UserPaymentMethod::query()
                ->where('id', $data['payment_method_id'])
                ->where('user_id', $user->id)
                ->where('type', UserPaymentMethod::TYPE_PAY_OUT)
                ->where('is_active', true)
                ->first();

            if (!$paymentMethod) {
                return response()->json(['message' => 'Moyen de retrait invalide'], 422);
            }
        } else {
            $paymentMethod = UserPaymentMethod::query()
                ->where('user_id', $user->id)
                ->where('type', UserPaymentMethod::TYPE_PAY_OUT)
                ->where('is_active', true)
                ->where('is_default', true)
                ->first();
        }

        $provider = $paymentMethod?->provider ?? strtolower((string) ($data['provider'] ?? ''));

        if (!in_array($provider, ['rib', 'paypal', 'stripe', 'apple_pay', 'google_pay'], true)) {
            return response()->json(['message' => 'Fournisseur de retrait non pris en charge'], 422);
        }

        $payout = DB::transaction(function () use ($wallet, $user, $amount, $provider, $paymentMethod): Payout {
            $payout = Payout::create([
                'liner_id' => $user->id,
                'payment_method_id' => $paymentMethod?->id,
                'amount' => $amount,
                'currency' => $wallet->currency,
                'provider' => $provider,
                'status' => 'pending',
                'requested_at' => now(),
                'metadata' => $paymentMethod ? [
                    'payment_method_id' => $paymentMethod->id,
                    'payment_method_label' => $paymentMethod->label,
                ] : null,
            ]);

            $wallet->decrement('balance', $amount);

            WalletTransaction::create([
                'wallet_id' => $wallet->id,
                'user_id' => $user->id,
                'type' => 'debit',
                'amount' => $amount,
                'description' => 'Demande de retrait',
                'reference_type' => Payout::class,
                'reference_id' => $payout->id,
            ]);

            return $payout;
        });

        ProcessPayoutRequest::dispatch($payout->id);

        return response()->json(['data' => $payout->fresh()], 202);
    }
}
