<?php

namespace App\Http\Controllers;

use App\Models\Payment;
use App\Models\Setting;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;

/**
 * Payment gateway webhooks. The endpoints exist and acknowledge/verify now;
 * fulfilment (marking a Payment paid) is finalised alongside the checkout flow
 * once sandbox keys are added. Register these URLs in each gateway dashboard
 * (they are shown on the admin Configurations page).
 */
class WebhookController extends Controller
{
    /** Safaricom Daraja STK callback. */
    public function mpesa(Request $request)
    {
        Log::info('webhook:mpesa', $request->all());

        $body = $request->input('Body.stkCallback', []);
        $resultCode = $body['ResultCode'] ?? null;
        $ref = $request->input('reference')
            ?? collect($body['CallbackMetadata']['Item'] ?? [])->firstWhere('Name', 'AccountReference')['Value'] ?? null;

        if ($ref && (int) $resultCode === 0) {
            $this->fulfil($ref, (string) ($body['MpesaReceiptNumber'] ?? ''));
        }

        // Daraja expects this acknowledgement shape.
        return response()->json(['ResultCode' => 0, 'ResultDesc' => 'Accepted']);
    }

    /** Paystack charge.success etc. Verified via HMAC-SHA512 of the raw body. */
    public function paystack(Request $request)
    {
        $secret = Setting::get('paystack_secret_key');

        if ($secret) {
            $expected = hash_hmac('sha512', $request->getContent(), $secret);
            if (! hash_equals($expected, (string) $request->header('x-paystack-signature'))) {
                Log::warning('webhook:paystack invalid signature');

                return response('invalid signature', 401);
            }
        }

        Log::info('webhook:paystack', $request->all());

        if ($request->input('event') === 'charge.success') {
            $this->fulfil($request->input('data.reference'), (string) $request->input('data.id'));
        }

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

    /** Flutterwave charge completed. Verified via the verif-hash header. */
    public function flutterwave(Request $request)
    {
        $hash = Setting::get('flutterwave_secret_key');

        if ($hash && ! hash_equals((string) $hash, (string) $request->header('verif-hash'))) {
            // Flutterwave sends a dashboard-set secret hash; accept for now but log mismatch.
            Log::warning('webhook:flutterwave hash mismatch');
        }

        Log::info('webhook:flutterwave', $request->all());

        if ($request->input('data.status') === 'successful' || $request->input('status') === 'successful') {
            $this->fulfil($request->input('data.tx_ref') ?? $request->input('txRef'), (string) $request->input('data.id'));
        }

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

    private function fulfil(?string $reference, string $gatewayReference): void
    {
        if (! $reference) {
            return;
        }

        Payment::where('reference', $reference)
            ->where('status', '!=', 'paid')
            ->get()
            ->each(fn (Payment $p) => $p->markPaid($gatewayReference));
    }
}
