<?php
/**
 * Alsendo - PrestaShop shipping module
 *
 * @author    Innovation Software
 * @copyright 2026 Innovation Software
 * @license   https://opensource.org/licenses/AFL-3.0  Academic Free License (AFL 3.0)
 */

namespace Alsendo\Services;

use Module;

/**
 * Reusable Segment helper for PrestaShop Addons Marketplace partner tracking.
 *
 * Emits module lifecycle events (Module Installed, Module Configured, ...) to
 * Segment so PrestaShop can monitor the module and handle revshare billing.
 *
 * The call is fully defensive: an empty write key, a missing Segment library or
 * any thrown error never propagates to the caller, so install/uninstall and
 * configuration flows can never be broken by tracking.
 */
class PrestashopModuleTracking
{
    /**
     * Send a tracking event to Segment.
     *
     * @param string $apiKey     Segment write key (empty => skip)
     * @param Module $module      module instance emitting the event
     * @param string $eventName   event label (e.g. "Module Installed")
     * @param array  $properties  extra, non-sensitive properties (max 10)
     *
     * @return void
     */
    public static function track($apiKey, Module $module, $eventName, array $properties = [])
    {
        if (empty($apiKey)) {
            self::log($module, sprintf('Skip "%s" because API key is empty.', $eventName));

            return;
        }

        $baseProperties = [
            'shop_url' => defined('_PS_BASE_URL_SSL_') ? _PS_BASE_URL_SSL_ : (defined('_PS_BASE_URL_') ? _PS_BASE_URL_ : ''),
            'ps_version' => defined('_PS_VERSION_') ? _PS_VERSION_ : '',
            'php_version' => PHP_VERSION,
            'module_version' => property_exists($module, 'version') ? $module->version : '',
        ];

        if (!empty($properties)) {
            $baseProperties['custom'] = $properties;
        }

        self::log($module, sprintf('Preparing "%s" tracking.', $eventName), $baseProperties);

        // Optional PsAccounts enrichment. The base PrestaShop Module class does not
        // expose getService(); this safely no-ops on modules without a service
        // container and only enriches when ps_accounts is wired up.
        try {
            if (method_exists($module, 'getService')) {
                $serviceName = sprintf('%s.ps_accounts_facade', $module->name);
                $accountsFacade = $module->getService($serviceName);
                if ($accountsFacade && method_exists($accountsFacade, 'getPsAccountsService')) {
                    $psAccountsService = $accountsFacade->getPsAccountsService();
                    // Only pseudonymous PrestaShop Account UUIDs -- never the merchant
                    // email or any PII (partner contract forbids sensitive data).
                    $baseProperties = array_merge($baseProperties, [
                        'user_id' => $psAccountsService->getUserUuid(),
                        'shop_id' => $psAccountsService->getShopUuid(),
                    ]);
                }
            }
        } catch (\Throwable $e) {
            if (class_exists('PrestaShopLogger')) {
                \PrestaShopLogger::addLog($e->getMessage(), 3, null, $module->name);
            }
        }

        try {
            if (class_exists('\\Segment')) {
                \Segment::init($apiKey);
                \Segment::track([
                    'anonymousId' => $module->name,
                    'event' => $eventName,
                    'properties' => $baseProperties,
                ]);
            } elseif (class_exists('\\Segment\\Segment')) {
                \Segment\Segment::init($apiKey);
                \Segment\Segment::track([
                    'anonymousId' => $module->name,
                    'event' => $eventName,
                    'properties' => $baseProperties,
                ]);
            } else {
                self::log($module, 'Segment library not available, aborting track call.');

                return;
            }

            self::log($module, sprintf('Track "%s" sent.', $eventName));
        } catch (\Throwable $e) {
            if (class_exists('PrestaShopLogger')) {
                \PrestaShopLogger::addLog($e->getMessage(), 3, null, $module->name);
            }
        }
    }

    /**
     * Log a tracking step. Verbose logging only runs under _PS_MODE_DEV_;
     * captured exceptions are logged separately at error level above.
     *
     * @param Module $module
     * @param string $message
     * @param array  $context
     *
     * @return void
     */
    protected static function log(Module $module, $message, array $context = [])
    {
        if (!class_exists('PrestaShopLogger')) {
            return;
        }

        if (!defined('_PS_MODE_DEV_') || !_PS_MODE_DEV_) {
            return;
        }

        \PrestaShopLogger::addLog(
            sprintf('[Tracking][%s] %s | Context: %s', $module->name, $message, json_encode($context)),
            1,
            null,
            $module->name
        );
    }
}
