<?php
/**
 * CryptoPayr gateway for Invision Community 4.x Commerce (Nexus).
 *
 * A redirect (off-site) gateway: the buyer is sent to the CryptoPayr hosted
 * checkout, and the transaction is approved from a signed webhook.
 *
 * Install: place under applications/nexus/sources/Gateways/CryptoPayr.php (or
 * ship as part of a plugin/app), then add a payment method of type "CryptoPayr"
 * in ACP → Commerce → Payments → Payment Methods.
 */

namespace IPS\nexus\Gateway;

if (!\defined('\IPS\SUITE_UNIQUE_KEY')) {
    header(($_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0') . ' 403 Forbidden');
    exit;
}

class _CryptoPayr extends \IPS\nexus\Gateway
{
    public static $supportsBilling = false;

    /** ACP settings for this gateway. */
    public function settings(&$form)
    {
        $settings = json_decode($this->settings, true) ?: array();
        $form->add(new \IPS\Helpers\Form\Text('cryptopayr_api_key', $settings['api_key'] ?? '', true));
        $form->add(new \IPS\Helpers\Form\Url('cryptopayr_api_base', $settings['api_base'] ?? 'https://cryptopayr.com', true));
    }

    public function testSettings($settings)
    {
        return array('api_key' => $settings['cryptopayr_api_key'], 'api_base' => rtrim($settings['cryptopayr_api_base'], '/'));
    }

    /**
     * Begin authorization → create the CryptoPayr payment and redirect the
     * buyer to the hosted checkout. The transaction is completed by the webhook.
     */
    public function auth(\IPS\nexus\Transaction $transaction, $values = null, \IPS\nexus\Customer\Card $card = null, $recurrings = array(), $source = null)
    {
        $settings = json_decode($this->settings, true);
        $amount   = $transaction->amount->amount->__toString();
        $currency = (string) $transaction->amount->currency;

        $payload = json_encode(array(
            'amount'      => (float) $amount,
            'currency'    => $currency,
            'metadata'    => 'ips_' . $transaction->id,
            'webhook_url' => (string) \IPS\Http\Url::internal('app=nexus&module=checkout&controller=external', 'front')->setQueryString(array('gateway' => 'cryptopayr')),
            'success_url' => (string) $transaction->invoice->checkoutUrl()->setQueryString('do', 'continue'),
        ));

        $res = \IPS\Http\Url::external(rtrim($settings['api_base'], '/') . '/api/v1/payment/create')
            ->request(30)
            ->setHeaders(array('Authorization' => 'Bearer ' . $settings['api_key'], 'Content-Type' => 'application/json'))
            ->post($payload)
            ->decodeJson();

        if (empty($res['data']['checkout_url'])) {
            throw new \IPS\nexus\Gateway\Exception('Could not start the crypto checkout.');
        }

        $transaction->status = $transaction::STATUS_PENDING;
        $transaction->save();

        \IPS\Output::i()->redirect(\IPS\Http\Url::external($res['data']['checkout_url']));
    }

    /**
     * Webhook entry — verify the signature and approve the matching transaction.
     * Wire this to the gateway's external return controller.
     */
    public static function handleWebhook()
    {
        $raw = file_get_contents('php://input');
        $sig = $_SERVER['HTTP_X_CRYPTOPAYR_SIGNATURE'] ?? '';
        $event = json_decode($raw, true);

        $txId = isset($event['metadata']) ? (int) str_replace('ips_', '', $event['metadata']) : 0;
        $transaction = $txId ? \IPS\nexus\Transaction::load($txId) : null;
        if (!$transaction) {
            return;
        }

        $settings = json_decode($transaction->method->settings, true);
        if (!$sig || !hash_equals(hash_hmac('sha256', $raw, $settings['api_key']), $sig)) {
            header(($_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0') . ' 400 Bad Request');
            exit;
        }

        if (strtoupper($event['status'] ?? '') === 'COMPLETED' && $transaction->status !== $transaction::STATUS_PAID) {
            $transaction->approve();
            $transaction->sendNotification();
        }
        echo 'OK';
    }
}
