<?php

namespace Sethrey\SysvoteWebsite;

/**
 * Minimal Stripe API client — no external dependency required.
 * Uses PHP cURL to communicate with Stripe's Checkout Sessions API.
 */
class StripeClient
{
    private string $secretKey;
    private string $apiBaseUrl = 'https://api.stripe.com/v1';

    public function __construct(string $secretKey)
    {
        $this->secretKey = $secretKey;
    }

    /**
     * Create a Stripe Checkout Session.
     *
     * @param array $params Checkout session parameters (mode, line_items, success_url, etc.)
     * @return array Stripe session data including the checkout URL
     * @throws \RuntimeException on API errors
     */
    public function createCheckoutSession(array $params): array
    {
        $url = $this->apiBaseUrl . '/checkout/sessions';
        
        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => http_build_query($params),
            CURLOPT_HTTPHEADER => [
                'Authorization: Bearer ' . $this->secretKey,
                'Content-Type: application/x-www-form-urlencoded',
            ],
            CURLOPT_TIMEOUT => 30,
        ]);

        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        curl_close($ch);

        if ($error) {
            throw new \RuntimeException('Stripe API request failed: ' . $error);
        }

        if ($httpCode !== 200) {
            throw new \RuntimeException('Stripe API error (HTTP ' . $httpCode . '): ' . $response);
        }

        $data = json_decode($response, true);
        if (json_last_error() !== JSON_ERROR_NONE) {
            throw new \RuntimeException('Failed to decode Stripe API response: ' . json_last_error_msg());
        }

        return $data;
    }

    /**
     * Retrieve a Stripe Checkout Session by ID.
     *
     * @param string $sessionId The Stripe session ID
     * @return array Session data
     * @throws \RuntimeException on API errors
     */
    public function retrieveCheckoutSession(string $sessionId): array
    {
        $url = $this->apiBaseUrl . '/checkout/sessions/' . $sessionId;
        
        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => [
                'Authorization: Bearer ' . $this->secretKey,
            ],
            CURLOPT_TIMEOUT => 30,
        ]);

        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        curl_close($ch);

        if ($error) {
            throw new \RuntimeException('Stripe API request failed: ' . $error);
        }

        if ($httpCode !== 200) {
            throw new \RuntimeException('Stripe API error (HTTP ' . $httpCode . '): ' . $response);
        }

        $data = json_decode($response, true);
        if (json_last_error() !== JSON_ERROR_NONE) {
            throw new \RuntimeException('Failed to decode Stripe API response: ' . json_last_error_msg());
        }

        return $data;
    }

    /**
     * Verify a Stripe webhook signature.
     *
     * @param string $payload Raw webhook payload
     * @param string $signature Stripe signature header (svi=1,t=...,v1=...)
     * @param string $webhookSecret Your webhook signing secret
     * @return bool True if signature is valid
     */
    public function verifyWebhookSignature(string $payload, string $signature, string $webhookSecret): bool
    {
        // Parse the signature header
        $elements = explode(',', $signature);
        $signatureData = [];
        
        foreach ($elements as $element) {
            $parts = explode('=', $element, 2);
            if (count($parts) === 2) {
                $signatureData[$parts[0]] = $parts[1];
            }
        }

        if (!isset($signatureData['t'], $signatureData['v1'])) {
            return false;
        }

        // Reconstruct the signed payload
        $signedPayload = $signatureData['t'] . '.' . $payload;
        $expectedSignature = hash_hmac('sha256', $signedPayload, $webhookSecret);

        // Use timing-safe comparison
        return hash_equals($expectedSignature, $signatureData['v1']);
    }
}
