<?php

namespace App\Http\Controllers\Api\V1;

use App\Domain\Financial\Enums\PaymentMethod;
use App\Domain\Financial\Enums\PaymentStatus;
use App\Domain\Financial\Models\Invoice;
use App\Domain\Financial\Models\Payment;
use App\Domain\Financial\Services\PaymobService;
use App\Http\Controllers\Controller;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;

class PaymentController extends Controller
{
    public function initiate(Request $request): JsonResponse
    {
        $request->validate([
            'invoice_uuid' => 'required|string',
        ]);

        $user = $request->user();
        $paymobService = new PaymobService($user->academy_id);

        if (!$paymobService->isConfigured()) {
            return response()->json([
                'error' => 'payment_not_configured',
                'message' => 'الدفع الإلكتروني غير مفعل حالياً، يرجى التواصل مع الإدارة',
            ], 503);
        }

        $invoice = Invoice::where('uuid', $request->invoice_uuid)
            ->whereIn('status', ['sent', 'partially_paid', 'overdue'])
            ->where('due_amount', '>', 0)
            ->first();

        if (!$invoice) {
            return response()->json([
                'error' => 'invoice_not_found',
                'message' => 'الفاتورة غير موجودة أو مدفوعة بالكامل',
            ], 404);
        }

        try {
            $result = $paymobService->createPaymentIntention($invoice, $user);

            Payment::create([
                'academy_id' => $invoice->academy_id,
                // Invoices have no branch_id column; take it from the
                // participant being billed so the payment is attributable.
                'branch_id' => $invoice->billable?->branch_id,
                'invoice_id' => $invoice->id,
                'reference' => 'PMB-' . $result['order_id'],
                'direction' => 'inbound',
                'method' => PaymentMethod::Online,
                'status' => PaymentStatus::Pending,
                'payer_type' => $invoice->billable_type,
                'payer_id' => $invoice->billable_id,
                'amount' => $invoice->due_amount,
                'currency' => 'EGP',
                'payment_date' => now()->toDateString(),
                'gateway_data' => [
                    'provider' => 'paymob',
                    'paymob_order_id' => $result['order_id'],
                ],
                'created_by' => $user->id,
            ]);

            return response()->json([
                'payment_url' => $result['iframe_url'],
                'payment_key' => $result['payment_key'],
                'order_id' => $result['order_id'],
                'amount' => $invoice->due_amount,
                'amount_display' => number_format($invoice->due_amount / 100, 2) . ' ج.م',
            ]);
        } catch (\Throwable $e) {
            Log::error('[Paymob] Payment initiation failed', [
                'invoice_uuid' => $invoice->uuid,
                'error' => $e->getMessage(),
            ]);

            return response()->json([
                'error' => 'payment_failed',
                'message' => 'فشل في بدء عملية الدفع، يرجى المحاولة لاحقاً',
            ], 500);
        }
    }

    public function callback(Request $request): JsonResponse
    {
        $data = $request->all();

        Log::info('[Paymob] Callback received', ['keys' => array_keys($data)]);

        // Paymob sends data in either flat format or nested under 'obj'
        $transactionData = $data['obj'] ?? $data;
        $orderId = $transactionData['order'] ?? ($transactionData['order']['id'] ?? null);

        if (!$orderId) {
            Log::warning('[Paymob] Callback missing order reference');
            return response()->json(['status' => 'missing_order'], 400);
        }

        // Find the payment to determine which academy's HMAC to use
        $payment = Payment::withoutGlobalScope('academy')
            ->where('status', PaymentStatus::Pending)
            ->whereJsonContains('gateway_data->paymob_order_id', (string) $orderId)
            ->first();

        if (!$payment) {
            Log::warning('[Paymob] No pending payment for callback order', ['order_id' => $orderId]);
            return response()->json(['status' => 'no_payment_found'], 404);
        }

        // Resolve credentials for the payment's academy
        $paymobService = PaymobService::forAcademy($payment->academy_id);

        if (!$paymobService->verifyCallback($transactionData)) {
            Log::warning('[Paymob] HMAC verification failed', ['order_id' => $orderId]);
            return response()->json(['status' => 'invalid_hmac'], 400);
        }

        $processed = $paymobService->processCallback($transactionData);

        if ($processed) {
            return response()->json(['status' => 'processed', 'payment_id' => $processed->id]);
        }

        return response()->json(['status' => 'not_processed']);
    }
}
