<?php
declare(strict_types=1);

require_once dirname(__DIR__) . '/payments.php';

final class StripeGateway implements PaymentGateway
{
    /** @param array<string,mixed> $settings */
    public function __construct(private array $settings)
    {
    }

    public function providerId(): string
    {
        return 'stripe';
    }

    public function createCheckout(array $input): array
    {
        $secret = trim((string) ($this->settings['stripe_secret_key'] ?? ''));
        if ($secret === '') {
            throw new RuntimeException('Stripe secret key is not configured.');
        }
        $amountCents = (int) round(((float) $input['amount']) * 100);
        if ($amountCents < 50) {
            throw new RuntimeException('Stripe minimum charge is $0.50.');
        }
        $currency = strtolower((string) ($input['currency'] ?? 'usd'));
        $params = [
            'mode' => 'payment',
            'success_url' => $input['success_url'],
            'cancel_url' => $input['cancel_url'],
            'line_items[0][price_data][currency]' => $currency,
            'line_items[0][price_data][product_data][name]' => $input['description'],
            'line_items[0][price_data][unit_amount]' => (string) $amountCents,
            'line_items[0][quantity]' => '1',
        ];
        if (!empty($input['customer_email'])) {
            $params['customer_email'] = (string) $input['customer_email'];
        }
        if (!empty($input['metadata']) && is_array($input['metadata'])) {
            foreach ($input['metadata'] as $k => $v) {
                $params['metadata[' . $k . ']'] = (string) $v;
            }
        }
        if (!empty($this->settings['enable_ach'])) {
            $params['payment_method_types[0]'] = 'card';
            $params['payment_method_types[1]'] = 'us_bank_account';
        }

        $resp = payment_http(
            'POST',
            'https://api.stripe.com/v1/checkout/sessions',
            [
                'Authorization: Bearer ' . $secret,
                'Content-Type: application/x-www-form-urlencoded',
            ],
            http_build_query($params)
        );
        if ($resp['status'] >= 400 || empty($resp['json']['id'])) {
            $msg = $resp['json']['error']['message'] ?? ('Stripe error HTTP ' . $resp['status']);
            throw new RuntimeException($msg);
        }
        return [
            'external_id' => (string) $resp['json']['id'],
            'checkout_url' => (string) ($resp['json']['url'] ?? ''),
            'status' => 'pending',
            'raw' => $resp['json'],
        ];
    }

    public function fetchStatus(string $externalId): array
    {
        $secret = trim((string) ($this->settings['stripe_secret_key'] ?? ''));
        $resp = payment_http(
            'GET',
            'https://api.stripe.com/v1/checkout/sessions/' . rawurlencode($externalId),
            ['Authorization: Bearer ' . $secret]
        );
        $paid = ($resp['json']['payment_status'] ?? '') === 'paid';
        return [
            'status' => $paid ? 'paid' : 'pending',
            'external_id' => $externalId,
            'raw' => $resp['json'] ?? [],
        ];
    }
}
