<?php

namespace App\Libraries\PaymentGateways;

use GuzzleHttp\Client;

class StripeGateway implements PaymentGatewayInterface
{
    private Client $http;
    private string $secretKey;
    private string $webhookSecret;

    public function __construct()
    {
        $this->secretKey     = env('stripe.secretKey');
        $this->webhookSecret = env('stripe.webhookSecret');
        $this->http = new Client(['base_uri' => 'https://api.stripe.com/v1/']);
    }

    public function charge(float $amount, string $currency, array $metadata = []): array
    {
        // Stripe amounts are in the smallest currency unit (e.g. paisa/cents).
        $response = $this->http->post('payment_intents', [
            'auth' => [$this->secretKey, ''],
            'form_params' => [
                'amount'   => (int) round($amount * 100),
                'currency' => strtolower($currency),
                'metadata' => $metadata,
            ],
        ]);

        $body = json_decode((string) $response->getBody(), true);

        return [
            'status'            => $body['status'] ?? 'pending',
            'redirect_url'      => null,
            'client_secret'     => $body['client_secret'] ?? null,
            'gateway_reference' => $body['id'] ?? null,
        ];
    }

    public function verifyWebhook(string $rawPayload, array $headers): array
    {
        $signature = $headers['Stripe-Signature'] ?? $headers['stripe-signature'] ?? '';

        // Stripe's signature scheme: t=timestamp,v1=hmac. Verified manually
        // here rather than pulling the full stripe-php SDK, to keep the
        // dependency footprint to what's declared in composer.json.
        $parts = [];
        foreach (explode(',', $signature) as $pair) {
            [$k, $v] = array_pad(explode('=', $pair, 2), 2, null);
            $parts[$k] = $v;
        }

        $signedPayload = ($parts['t'] ?? '') . '.' . $rawPayload;
        $expectedSig = hash_hmac('sha256', $signedPayload, $this->webhookSecret);

        $verified = isset($parts['v1']) && hash_equals($expectedSig, $parts['v1']);
        $body = json_decode($rawPayload, true) ?? [];

        return [
            'verified'               => $verified,
            'gateway_transaction_id' => $body['data']['object']['id'] ?? null,
            'status'                 => $body['data']['object']['status'] ?? null,
            'raw'                    => $body,
        ];
    }

    public function refund(string $gatewayTransactionId, float $amount): array
    {
        $response = $this->http->post('refunds', [
            'auth' => [$this->secretKey, ''],
            'form_params' => [
                'payment_intent' => $gatewayTransactionId,
                'amount'         => (int) round($amount * 100),
            ],
        ]);

        $body = json_decode((string) $response->getBody(), true);
        return ['status' => $body['status'] ?? 'failed', 'raw' => $body];
    }

    public function getStatus(string $gatewayTransactionId): array
    {
        $response = $this->http->get("payment_intents/{$gatewayTransactionId}", ['auth' => [$this->secretKey, '']]);
        $body = json_decode((string) $response->getBody(), true);
        return ['status' => $body['status'] ?? 'unknown', 'raw' => $body];
    }
}
