<?php
/**
 * 2026 Paysera
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Academic Free License (AFL 3.0)
 * that is bundled with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://opensource.org/licenses/afl-3.0.php
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@prestashop.com so we can send you a copy immediately.
 *
 * @author Paysera <plugins@paysera.com>
 * @copyright 2026 Paysera
 * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
 * International Registered Trademark & Property of Paysera
 */

declare(strict_types=1);

use Paysera\PrestashopPayments\Controller\AbstractPayseraFrontController;
use Paysera\PrestashopPayments\Factory\RequestFactory;
use Paysera\PrestashopPayments\Handler\CallbackResponseHandler;
use Paysera\PrestashopPayments\Logger\PayseraLogger;
use Psr\Http\Message\ServerRequestInterface;

if (!defined('_PS_VERSION_')) {
    exit;
}

class PayserapaymentsCallbackModuleFrontController extends AbstractPayseraFrontController
{
    public function init()
    {
        parent::init();
        $this->ajax = true;
    }

    public function postProcess(): void
    {
        $request = $this->get(RequestFactory::class)->createFromGlobals();

        $this->logIncomingRequest($request);

        try {
            $response = $this->get(CallbackResponseHandler::class)->handleCallback($request);

            $this->logger()->info('Callback handled', [
                'http_code' => $response->getHttpCode(),
            ]);

            http_response_code($response->getHttpCode());
            $this->ajaxRender($response->getMessage());
        } catch (Throwable $e) {
            $this->logCallbackFailure($e);

            http_response_code(500);
            $this->ajaxRender(json_encode(['error' => 'Internal server error']));
        }
    }

    private function logIncomingRequest(ServerRequestInterface $request): void
    {
        try {
            $body = (string) $request->getBody();
            $this->logger()->info('Paysera callback received', [
                'method' => $request->getMethod(),
                'content_type' => $request->getHeaderLine('Content-Type'),
                'content_length' => strlen($body),
                'query_string' => $request->getUri()->getQuery(),
                'body_snippet' => mb_substr($body, 0, 1024),
            ]);
        } catch (Throwable $loggerFailure) {
            // Logger failure shouldn't break callback processing.
        }
    }

    private function logCallbackFailure(Throwable $e): void
    {
        try {
            $this->get(PayseraLogger::class)->error('Uncaught exception in callback handler', [
                'exception' => get_class($e),
                'message' => $e->getMessage(),
                'file' => $e->getFile(),
                'line' => $e->getLine(),
            ]);
        } catch (Throwable $loggerFailure) {
            // Logger itself failed (container broken, DB down); PHP's error log still captures $e.
        }
    }
}
