<?php

/**
 * Copyright 2024-2025 Simply.IN Sp. z o.o.
 *
 * NOTICE OF LICENSE
 *
 * Licensed under the EUPL-1.2 or later.
 * You may not use this work except in compliance with the Licence.
 *
 * Copy of the Licence is available at:
 * https://joinup.ec.europa.eu/software/page/eupl
 * It is bundled with this package in the file LICENSE.txt
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the Licence is distributed on an as is basis,
 * without warranties or conditions of any kind, either express or implied.
 * Check the Licence for the specific language governing permissions
 * and limitations under the License.
 *
 * @author   Simply.IN Sp. z o.o.
 * @copyright 2024-2025 Simply.IN Sp. z o.o.
 * @license   https://joinup.ec.europa.eu/software/page/eupl
 */

declare(strict_types=1);

use SimplyIn\Ajax\AjaxRegistryFactory;
use SimplyIn\Ajax\AjaxRequest;
use SimplyIn\Ajax\AjaxTokenValidator;

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

class SimplyinAjaxModuleFrontController extends ModuleFrontController
{
    /** @var Simplyin|null */
    public $module;

    public function __construct()
    {
        parent::__construct();

        if (!Tools::isSubmit('ajax')) {
            exit;
        }

        $this->module = Module::getInstanceByName('simplyin');
    }

    public function initContent(): void
    {
        parent::initContent();
    }

    public function displayAjax(): void
    {
        $request = new AjaxRequest();
        $validator = new AjaxTokenValidator($this->module);
        if (!$validator->isValid($request)) {
            exit(json_encode(['error' => 'Invalid token']));
        }

        if (!Tools::isSubmit('action')) {
            exit(json_encode(['error' => 'No action specified']));
        }

        $registry = AjaxRegistryFactory::create($this->module, $this->context);

        try {
            $response = $registry->dispatch((string) Tools::getValue('action'), $request);
        } catch (\Throwable $e) {
            // Log file:line + trace (not just the message) so preprod can pinpoint which call threw.
            PrestaShopLogger::addLog(
                'SimplyIn ajax action "' . Tools::getValue('action') . '" failed: ' . $e->getMessage()
                . ' @ ' . $e->getFile() . ':' . $e->getLine() . "\n" . $e->getTraceAsString(),
                3,
            );
            exit(json_encode(['error' => 'Internal error']));
        }

        // Never emit an empty body on an un-encodable payload (e.g. malformed UTF-8 from upstream) —
        // that is exactly the "silence" the widget cannot react to. Substitute bad bytes, and on a
        // hard encode failure return an explicit JSON error the front can surface.
        $encoded = json_encode($response, JSON_INVALID_UTF8_SUBSTITUTE);
        if ($encoded === false) {
            PrestaShopLogger::addLog(
                'SimplyIn ajax action "' . Tools::getValue('action') . '" response encode failed: ' . json_last_error_msg(),
                3,
            );
            $encoded = json_encode(['error' => 'Internal error']);
        }

        exit($encoded);
    }
}
