<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Http\Requests\CreateCardPaymentRequest;
use App\Http\Requests\CreatePixRequest;
use App\Models\Payment;
use App\Services\MercadoPagoService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;

class PaymentController extends Controller
{
    public function __construct(private MercadoPagoService $mp) {}

    /**
     * POST /api/payments/pix
     */
    public function createPix(CreatePixRequest $request): JsonResponse
    {
        $user = $request->user();
        $externalRef = 'wallet-' . $user->id . '-' . Str::uuid();

        try {
            $result = $this->mp->createPix([
                'amount'             => $request->input('amount'),
                'external_reference' => $externalRef,
                'payer' => [
                    'email'      => $request->input('payer.email'),
                    'first_name' => $request->input('payer.first_name'),
                    'last_name'  => $request->input('payer.last_name'),
                    'document'   => $request->input('payer.document'),
                ],
            ]);

            // Persiste localmente
            $payment = Payment::create([
                'user_id'            => $user->id,
                'mp_payment_id'      => $result['id'],
                'external_reference' => $externalRef,
                'amount'             => $request->input('amount'),
                'method'             => 'pix',
                'status'             => $result['status'],
                'pix_qr_code'        => $result['qr_code'],
                'pix_qr_code_base64' => $result['qr_code_base64'],
                'pix_ticket_url'     => $result['ticket_url'],
                'expires_at'         => $result['expires_at'],
            ]);

            return response()->json([
                'id'              => $payment->id,
                'mp_payment_id'   => $result['id'],
                'status'          => $result['status'],
                'qr_code'         => $result['qr_code'],
                'qr_code_base64'  => $result['qr_code_base64'],
                'ticket_url'      => $result['ticket_url'],
                'expires_at'      => $result['expires_at'],
            ]);
        } catch (\Throwable $e) {
            Log::error('[PIX] erro ao criar pagamento', ['error' => $e->getMessage()]);
            return response()->json([
                'message' => 'Não foi possível gerar o PIX',
                'details' => $e->getMessage(),
            ], 500);
        }
    }

    /**
     * POST /api/payments/card
     */
    public function createCard(CreateCardPaymentRequest $request): JsonResponse
    {
        $user = $request->user();
        $externalRef = 'wallet-' . $user->id . '-' . Str::uuid();

        try {
            $result = $this->mp->createCardPayment([
                'token'             => $request->input('token'),
                'payment_method_id' => $request->input('payment_method_id'),
                'issuer_id'         => $request->input('issuer_id'),
                'installments'      => $request->input('installments'),
                'amount'            => $request->input('amount'),
                'external_reference' => $externalRef,
                'payer' => [
                    'email'    => $request->input('payer.email'),
                    'document' => $request->input('payer.document'),
                ],
            ]);

            $payment = Payment::create([
                'user_id'            => $user->id,
                'mp_payment_id'      => $result['id'],
                'external_reference' => $externalRef,
                'amount'             => $request->input('amount'),
                'method'             => 'credit_card',
                'status'             => $result['status'],
                'status_detail'      => $result['status_detail'],
                'installments'       => $result['installments'],
                'approved_at'        => $result['status'] === 'approved' ? now() : null,
            ]);

            // Crédito imediato no caso de aprovação síncrona
            if ($result['status'] === 'approved') {
                $this->creditUserBalance($payment);
            }

            return response()->json([
                'id'                 => $payment->id,
                'mp_payment_id'      => $result['id'],
                'status'             => $result['status'],
                'status_detail'      => $result['status_detail'],
                'transaction_amount' => $result['transaction_amount'],
                'installments'       => $result['installments'],
            ]);
        } catch (\Throwable $e) {
            Log::error('[CARD] erro ao criar pagamento', ['error' => $e->getMessage()]);
            return response()->json([
                'message' => 'Não foi possível processar o pagamento',
                'details' => $e->getMessage(),
            ], 500);
        }
    }

    /**
     * GET /api/payments/{id}/status
     * Usado no polling do PIX.
     */
    public function status(Request $request, int $id): JsonResponse
    {
        $payment = Payment::where('user_id', $request->user()->id)->findOrFail($id);

        // Se ainda pendente, pergunta direto pro MP (fonte da verdade)
        if ($payment->isPending() && $payment->mp_payment_id) {
            try {
                $remote = $this->mp->getPayment($payment->mp_payment_id);

                if ($remote['status'] !== $payment->status) {
                    $payment->update([
                        'status'        => $remote['status'],
                        'status_detail' => $remote['status_detail'],
                        'approved_at'   => $remote['status'] === 'approved' ? now() : null,
                    ]);

                    if ($remote['status'] === 'approved') {
                        $this->creditUserBalance($payment->refresh());
                    }
                }
            } catch (\Throwable $e) {
                Log::warning('[STATUS] consulta remota falhou', ['error' => $e->getMessage()]);
            }
        }

        return response()->json([
            'id'            => $payment->id,
            'mp_payment_id' => $payment->mp_payment_id,
            'status'        => $payment->status,
            'status_detail' => $payment->status_detail,
            'amount'        => $payment->amount,
            'method'        => $payment->method,
            'approved_at'   => $payment->approved_at,
        ]);
    }

    /**
     * Credita o saldo na carteira do usuário.
     * Idempotente: só credita se o pagamento ainda não foi creditado.
     */
    public function creditUserBalance(Payment $payment): void
    {
        // Garante idempotência
        if (! $payment->isApproved()) return;

        // Lock pra evitar race condition do webhook + polling
        \DB::transaction(function () use ($payment) {
            $fresh = Payment::lockForUpdate()->find($payment->id);

            // Se já foi creditado em outro processo, pula
            if ($fresh->approved_at && $fresh->wasRecentlyCredited ?? false) return;

            // TODO: substitua pela sua lógica real de carteira
            $user = $fresh->user;
            $user->wallet_balance = ($user->wallet_balance ?? 0) + $fresh->amount;
            $user->save();

            // Marca como creditado (você pode adicionar uma coluna `credited_at` se quiser)
            $fresh->update(['approved_at' => $fresh->approved_at ?? now()]);

            Log::info('[CREDIT] saldo creditado', [
                'user_id' => $user->id,
                'amount'  => $fresh->amount,
                'payment' => $fresh->id,
            ]);
        });
    }
}