<?php

namespace PortalPeople\redsys\controllers\api;

use Yii;
use yii\rest\Controller;
use PortalPeople\redsys\models\Redsys;

class PaymentsController extends Controller
{
    /**
     * Build Redsys payment payload (GET v3/payments/redsys-request)
     * Called by the host app to get the signed form data to post to Redsys.
     */
    public function actionRequest()
    {
        $request = Yii::$app->request;
        $params  = Yii::$app->params['redsys'] ?? [];

        $model = new Redsys();
        $model->DS_MERCHANT_ORDER           = $request->get('order', uniqid());
        $model->DS_MERCHANT_MERCHANTCODE    = $params['merchant_code'] ?? '';
        $model->DS_MERCHANT_TERMINAL        = $params['terminal']      ?? '1';
        $model->DS_MERCHANT_CURRENCY        = $params['currency']      ?? '978';
        $model->DS_MERCHANT_TRANSACTIONTYPE = $params['transaction_type'] ?? '0';
        $model->DS_MERCHANT_AMOUNT          = (string)(int)round((float)$request->get('amount', 0) * 100);
        $model->DS_MERCHANT_IDENTIFIER      = $request->get('identifier', '');
        $model->DS_MERCHANT_COF_INI         = 'N';
        $model->DS_MERCHANT_DIRECTPAYMENT   = 'false';
        $model->DS_MERCHANT_EXCEP_SCA       = 'LWV';

        $apiUrl = ($params['environment'] ?? 'production') === 'sandbox'
            ? Redsys::SANDBOX_URL
            : Redsys::PRODUCTION_URL;

        return [
            'url'                   => $apiUrl,
            'Ds_SignatureVersion'   => Redsys::Ds_SignatureVersion,
            'Ds_MerchantParameters' => $model->getDs_MerchantParameters(),
            'Ds_Signature'          => $model->getDs_Signature(),
        ];
    }

    /**
     * Handle Redsys payment response redirect (GET v3/payments/redsys)
     * Redsys redirects the customer back here after payment.
     */
    public function actionPayment()
    {
        $request        = Yii::$app->request;
        $merchantParams = $request->get('Ds_MerchantParameters', '');
        $signature      = $request->get('Ds_Signature', '');

        if (empty($merchantParams) || empty($signature)) {
            Yii::$app->response->statusCode = 400;
            return ['error' => 'Missing Redsys response parameters'];
        }

        $error = $this->verifySignature($merchantParams, $signature);
        if ($error) {
            return $error;
        }

        $decoded = json_decode(Redsys::base64_url_decode_safe($merchantParams), true);
        if (!$decoded) {
            Yii::$app->response->statusCode = 400;
            return ['error' => 'Invalid merchant parameters encoding'];
        }

        $responseCode = (int)($decoded['Ds_Response'] ?? 9999);
        $success      = $responseCode <= 99;

        Yii::info([
            'event'         => 'redsys_payment_response',
            'order'         => $decoded['Ds_Order']  ?? null,
            'amount'        => $decoded['Ds_Amount'] ?? null,
            'response_code' => $responseCode,
            'success'       => $success,
        ], 'redsys');

        return [
            'success'   => $success,
            'order'     => $decoded['Ds_Order']               ?? null,
            'amount'    => $decoded['Ds_Amount']              ?? null,
            'currency'  => $decoded['Ds_Currency']            ?? null,
            'auth_code' => $decoded['Ds_AuthorisationCode']   ?? null,
            'response'  => $responseCode,
        ];
    }

    /**
     * Handle Redsys server-to-server notification (POST webhook)
     */
    public function actionWebhook()
    {
        $request        = Yii::$app->request;
        $merchantParams = $request->post('Ds_MerchantParameters', '');
        $signature      = $request->post('Ds_Signature', '');

        if (empty($merchantParams) || empty($signature)) {
            Yii::$app->response->statusCode = 400;
            return ['error' => 'Missing webhook parameters'];
        }

        $error = $this->verifySignature($merchantParams, $signature);
        if ($error) {
            return $error;
        }

        $decoded = json_decode(Redsys::base64_url_decode_safe($merchantParams), true);
        if (!$decoded) {
            Yii::$app->response->statusCode = 400;
            return ['error' => 'Invalid merchant parameters encoding'];
        }

        $responseCode = (int)($decoded['Ds_Response'] ?? 9999);
        $success      = $responseCode <= 99;

        Yii::info([
            'event'         => 'redsys_webhook',
            'order'         => $decoded['Ds_Order']  ?? null,
            'amount'        => $decoded['Ds_Amount'] ?? null,
            'response_code' => $responseCode,
            'success'       => $success,
        ], 'redsys');

        return ['status' => 'ok', 'success' => $success];
    }

    /**
     * Verify Redsys HMAC-SHA-512 signature.
     * Returns null on success, or an error array on failure.
     */
    private function verifySignature(string $merchantParams, string $receivedSig): ?array
    {
        $secret = Redsys::getSecretKey();
        if (empty($secret)) {
            Yii::error('Redsys secret key not configured', __METHOD__);
            Yii::$app->response->statusCode = 500;
            return ['error' => 'Gateway configuration error'];
        }

        // Derive order from decoded params to diversify the key
        $decoded = json_decode(Redsys::base64_url_decode_safe($merchantParams), true);
        $order   = $decoded['Ds_Order'] ?? '';

        $expected = Redsys::createMerchantSignature($secret, $merchantParams, $order);

        if (!hash_equals($expected, $receivedSig)) {
            Yii::error([
                'event'    => 'redsys_signature_mismatch',
                'expected' => $expected,
                'received' => $receivedSig,
            ], __METHOD__);
            Yii::$app->response->statusCode = 403;
            return ['error' => 'Invalid signature'];
        }

        return null;
    }
}
