<?php
namespace PortalPeople\paygate\models;
use backend\models\Cartsbe;
use Yii;

class Paygate extends \common\models\DynamicModel
{
    /** @deprecated Use getSecretKey() — runtime constant placeholder */
    public const Ds_KEY = '';

    /** Computop Paygate test base API URL */
    public const SANDBOX_URL = 'https://test.computop-paygate.com/api/v2';

    /** Computop Paygate production base API URL */
    public const PRODUCTION_URL = 'https://www.computop-paygate.com/api/v2';

    /** Computop test OAuth token base URL (prefix for /authorization/oauth/token) */
    public const SANDBOX_OAUTH_URL = 'https://test.computop-paygate.com';

    /** Computop production OAuth token base URL */
    public const PRODUCTION_OAUTH_URL = 'https://www.computop-paygate.com';

    /**
     * Get Computop Paygate secret/signing key.
     * Loads from Yii::$app->params['paygate']['secret_key'], falls back to PAYGATE_SECRET_KEY env var.
     */
    public static function getSecretKey(): string
    {
        if (isset(Yii::$app->params['paygate']['secret_key'])) {
            return Yii::$app->params['paygate']['secret_key'];
        }
        $envKey = getenv('PAYGATE_SECRET_KEY');
        return $envKey ?: '';
    }

    /** @deprecated Use getSecretKey() */
    public static function getDsKey(): string
    {
        return self::getSecretKey();
    }

    public static function localAttributes()
    {
        return [];
    }

    /**
     * Request OAuth2 token from Computop Paygate
     * @param string $clientId
     * @param string $clientSecret
     * @param string $apiUrl
     * @return array [success, token, error]
     */
    public static function requestOAuth2Token($clientId, $clientSecret, $apiUrl)
    {
        $client = new \yii\httpclient\Client();
        $response = $client->createRequest()
            ->setMethod('POST')
            ->setUrl($apiUrl)
            ->setHeaders(['Content-Type' => 'application/x-www-form-urlencoded'])
            ->setData([
                'grant_type' => 'client_credentials',
                'client_id' => $clientId,
                'client_secret' => $clientSecret,
            ])
            ->send();

        if (!$response->isOk) {
            return [
                'success' => false,
                'token' => null,
                'error' => $response->getContent(),
            ];
        }
        $data = $response->getData();
        if (isset($data['access_token'])) {
            return [
                'success' => true,
                'token' => $data['access_token'],
                'error' => null,
            ];
        }
        return [
            'success' => false,
            'token' => null,
            'error' => $data['error_description'] ?? 'Unknown error',
        ];
    }

    /**
     * Basic Auth header generator for API key
     * @param string $apiKey
     * @return string Authorization header value
     */
        /**
         * Get current environment (sandbox/production).
         */
        public static function getEnvironment(): string
        {
            $env = getenv('PAYGATE_ENVIRONMENT') ?: (Yii::$app->params['paygate']['environment'] ?? 'sandbox');
            return strtolower($env);
        }

        /**
         * Basic Auth header value for Computop API.
         * Format: Basic base64(MerchantID:APIKey)
         * @param string $merchantId
         * @param string $apiKey
         * @return string Authorization header value (the value only, not the header name)
         */
        public static function getBasicAuthHeader($merchantId, $apiKey)
        {
            return 'Basic ' . base64_encode($merchantId . ':' . $apiKey);
        }

        /**
         * Get Computop Paygate API URL based on environment.
         * @param string $type 'api' for REST API base URL, 'oauth' for OAuth token base URL
         * @return string
         */
        public static function getApiUrl($type = 'api')
        {
            $isProduction = self::getEnvironment() === 'production';
            if ($type === 'oauth') {
                return $isProduction ? self::PRODUCTION_OAUTH_URL : self::SANDBOX_OAUTH_URL;
            }
            return $isProduction ? self::PRODUCTION_URL : self::SANDBOX_URL;
        }
    /**
     * Create a Computop Paygate checkout session (POST /payments/sessions).
     * Returns hosted payment page URL for customer redirect, or error details.
     * @param Cartsbe $cart
     * @return array ['success' => bool, 'paymentUrl' => string|null, 'payId' => string|null, 'error' => string|null]
     */
    public static function getPayload(Cartsbe $cart)
    {
        $merchantId = Yii::$app->params['paygate']['merchant_code'] ?? '';
        $apiKey = Yii::$app->params['paygate']['api_key'] ?? getenv('PAYGATE_API_KEY') ?: '';
        $currency = strtoupper(Yii::$app->params['paygate']['currency_iso'] ?? 'EUR');
        $returnUrl = Yii::$app->params['paygate']['success_url'] ?? '';
        $cancelUrl = Yii::$app->params['paygate']['error_url'] ?? '';

        $payload = [
            'order' => [
                'orderId' => (string)$cart->id,
                'amount' => intval($cart->total * 100),
                'currency' => $currency,
            ],
            'payment' => [
                'returnUrl' => $returnUrl,
                'cancelUrl' => $cancelUrl,
            ],
        ];

        $httpClient = new \yii\httpclient\Client();
        $response = $httpClient->createRequest()
            ->setMethod('POST')
            ->setUrl(self::getApiUrl('api') . '/payments/sessions')
            ->setHeaders([
                'Content-Type' => 'application/json',
                'Accept' => 'application/json',
                'Authorization' => self::getBasicAuthHeader($merchantId, $apiKey),
            ])
            ->setContent(json_encode($payload))
            ->send();

        if (!$response->isOk) {
            return ['success' => false, 'paymentUrl' => null, 'payId' => null, 'error' => 'Computop API error: ' . $response->statusCode];
        }

        $data = $response->getData();
        return [
            'success' => true,
            'paymentUrl' => $data['paymentUrl'] ?? null,
            'payId' => $data['payId'] ?? null,
            'error' => null,
        ];
    }

    /**
     * Process Computop Paygate payment notification (webhook POST or GET redirect callback).
     * Verifies HMAC-SHA-256 signature if provided.
     * @param string $body JSON webhook body (raw request body)
     * @param string $signature HMAC signature from request header (optional)
     * @return array Payment data including 'payId', 'status', 'signature_valid'
     */
    public static function processResponse($body, $signature = '')
    {
        if ($body === '') {
            return ['error' => 'Empty response body', 'signature_valid' => false];
        }

        $data = json_decode($body, true);
        if ($data === null) {
            return ['error' => 'Invalid JSON in response body', 'signature_valid' => false];
        }

        if ($signature !== '') {
            $secret = self::getSecretKey();
            $valid = self::verifySignature($body, $signature, $secret);
            $data['signature_valid'] = $valid;
        } else {
            $data['signature_valid'] = null; // Signature not provided — not verified
        }

        return $data;
    }

    /**
     * Sign payload with HMAC-SHA-256 for Computop webhook verification.
     */
    public static function signPayload($payload, $secret)
    {
        return base64_encode(hash_hmac('sha256', $payload, $secret, true));
    }

    /**
     * Verify Computop webhook HMAC-SHA-256 signature.
     * @param string $payload Raw JSON webhook body
     * @param string $signature Base64-encoded signature from request header
     * @param string $secret Shared secret key
     */
    public static function verifySignature($payload, $signature, $secret)
    {
        $expected = self::signPayload($payload, $secret);
        return hash_equals($expected, $signature);
    }
}