<?php

namespace App\Services\Gateways;

use App\Contracts\PaymentGatewayInterface;
use App\Models\Order;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;

/**
 * Exactly Payments gateway.
 *
 * Docs: https://docs.exactlypayments.com
 * When you receive API credentials, fill in:
 *   - EXACTLY_API_URL   (e.g. https://api.exactlypayments.com/v1)
 *   - EXACTLY_API_KEY   (from Exactly dashboard → Developers → API Keys)
 *   - EXACTLY_MERCHANT_ID
 *   - EXACTLY_WEBHOOK_SECRET  (from Exactly dashboard → Webhooks)
 */
class ExactlyGateway implements PaymentGatewayInterface
{
    private string $apiUrl;
    private string $apiKey;
    private string $merchantId;
    private string $webhookSecret;

    public function __construct(string $apiKey, string $merchantId, string $webhookSecret)
    {
        $this->apiUrl        = rtrim(config('payment.exactly_api_url', 'https://api.exactlypayments.com/v1'), '/');
        $this->apiKey        = $apiKey;
        $this->merchantId    = $merchantId;
        $this->webhookSecret = $webhookSecret;
    }

    public function createSession(Order $order, string $returnUrl, string $cancelUrl): array
    {
        $response = Http::withToken($this->apiKey)
            ->post("{$this->apiUrl}/payment-sessions", [
                'merchant_id'    => $this->merchantId,
                'order_id'       => $order->order_number,
                'amount'         => (int) round($order->total * 100), // pence
                'currency'       => $order->currency ?? 'GBP',
                'description'    => "BioSupply UK order {$order->order_number}",
                'customer_email' => $order->user?->email ?? $order->guest_email,
                'return_url'     => $returnUrl,
                'cancel_url'     => $cancelUrl,
                'metadata'       => ['order_id' => $order->id],
            ]);

        if (!$response->successful()) {
            Log::error('Exactly: createSession failed', ['response' => $response->json()]);
            throw new \RuntimeException('Payment session could not be created. Please try again.');
        }

        $data = $response->json();

        return [
            'session_id'   => $data['id'],           // TODO: confirm field name from docs
            'redirect_url' => $data['payment_url'],  // TODO: confirm field name from docs
        ];
    }

    public function getSessionStatus(string $sessionId): string
    {
        $response = Http::withToken($this->apiKey)
            ->get("{$this->apiUrl}/payment-sessions/{$sessionId}");

        if (!$response->successful()) {
            return 'pending';
        }

        $status = $response->json('status'); // TODO: confirm field + value names from docs

        return match ($status) {
            'paid', 'completed', 'success' => 'paid',
            'failed', 'declined', 'expired' => 'failed',
            default => 'pending',
        };
    }

    public function handleWebhook(array $payload, string $rawBody, string $signature): ?string
    {
        // Verify HMAC signature
        $expected = hash_hmac('sha256', $rawBody, $this->webhookSecret);
        if (!hash_equals($expected, $signature)) {
            return null;
        }

        $status = $payload['status'] ?? null; // TODO: confirm field names from docs

        if (in_array($status, ['paid', 'completed', 'success'])) {
            return $payload['order_id'] ?? null; // returns order_number
        }

        return null;
    }
}
