<?php

namespace App\Http\Controllers;

use App\Models\Billing;
use App\Services\BillingPaymentService;
use App\Services\DuitkuService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;

/**
 * Menerima callback (server-to-server) dari Duitku.
 *
 * Route publik & CSRF-exempt. Verifikasi murni via signature MD5 + cek amount.
 * Tidak pernah mempercayai return URL untuk kredit — callback adalah source-of-truth.
 */
class DuitkuCallbackController extends Controller
{
    public function __construct(
        private readonly DuitkuService $duitkuService,
        private readonly BillingPaymentService $billingPaymentService,
    ) {}

    public function __invoke(Request $request)
    {
        $payload = $request->all();

        if (! $this->duitkuService->validCallback($payload)) {
            Log::warning('Duitku callback: invalid signature', [
                'merchantOrderId' => $payload['merchantOrderId'] ?? null,
            ]);

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

        $merchantOrderId = (string) $payload['merchantOrderId'];
        $amount = (string) $payload['amount'];

        $billing = Billing::where('no_invoice', $merchantOrderId)->first();

        if (! $billing) {
            Log::warning('Duitku callback: unknown invoice', ['merchantOrderId' => $merchantOrderId]);

            return response('unknown invoice', 404);
        }

        // Cek amount cocok dengan total billing.
        if ((int) $amount !== (int) $billing->total) {
            Log::warning('Duitku callback: amount mismatch', [
                'invoice' => $merchantOrderId,
                'expected' => $billing->total,
                'got' => $amount,
            ]);

            return response('amount mismatch', 422);
        }

        // Simpan payload callback untuk audit (terlepas dari result code).
        $billing->update([
            'duitku_callback_payload' => $payload,
            'duitku_callback_received_at' => now(),
            'duitku_reference' => $payload['reference'] ?? $billing->duitku_reference,
        ]);

        if (! $this->duitkuService->isSuccessfulCallback($payload)) {
            Log::info('Duitku callback: non-success result, no credit', [
                'invoice' => $merchantOrderId,
                'resultCode' => $payload['resultCode'] ?? null,
            ]);

            return response('ignored', 200);
        }

        $paid = $this->billingPaymentService->markPaid($billing, [
            'reference' => $payload['reference'] ?? null,
            'payload' => $payload,
        ]);

        Log::info('Duitku callback processed', [
            'invoice' => $merchantOrderId,
            'newly_paid' => $paid,
        ]);

        // Selalu 200 agar Duitku tidak retry callback yang valid berulang.
        return response('success', 200);
    }
}
