<?php

require_once(MH_DIR_FS_CATALOG . MH_ROOT_PATH . 'common/classes/mailbeez.php');
require_once(MH_DIR_FS_CATALOG . MH_ROOT_PATH . 'common/classes/esp_event_adapter_factory.php');
require_once(MH_DIR_FS_CATALOG . MH_ROOT_PATH . 'common/classes/esp_event_repository.php');
require_once(MH_DIR_FS_CATALOG . MH_ROOT_PATH . 'common/classes/esp_event_processor.php');

class service_handler_esp_event extends mailbeez
{
    function __construct()
    {
        parent::__construct();

        $this->code = 'service_handler_esp_event';
        $this->module = 'service_handler_esp_event';
        $this->version = '1.0';
        $this->required_mb_version = 4.6;
        $this->iteration = 1;
        $this->title = mh_lng('MAILBEEZ_ESP_EVENT_HNDL_TEXT_TITLE', 'ESP Event Handler');
        $this->description = mh_lng('MAILBEEZ_ESP_EVENT_HNDL_TEXT_DESCRIPTION', 'Handles ESP webhook events.');
        $this->sort_order = 20001;
        $this->enabled = true;
        $this->admin_action_plugins = '';
        $this->common_admin_action_plugins = '';
        $this->is_editable = false;
        $this->is_configurable = false;
        $this->removable = false;
        $this->hidden = true;

        $this->allow_preview = false;
        $this->allow_reporting = false;
        $this->allow_timing = false;
        $this->allow_group_filter_check = false;
    }

    function service_handler_esp_event()
    {
        self::__construct();
    }

    function getAudience()
    {
        return false;
    }

    function check()
    {
        return true;
    }

    function remove()
    {
        return false;
    }

    function install()
    {
        return false;
    }

    function process($audience = '', $mode = '')
    {
        return -1;
    }

    function external_event($external_call = 'True')
    {

        if (strtoupper((string)mh_server('REQUEST_METHOD')) !== 'POST') {
            $this->sendJson(405, array('ok' => false, 'error' => 'ESP event handler: method_not_allowed'));
        }

        $provider = $this->getConfiguredProvider();
        if ($provider === '') {
            $this->sendJson(403, array('ok' => false, 'error' => 'ESP event handler: provider_not_active'));
        }

        $requestedProvider = $this->normalizeProvider(mh_get('provider', ''));
        if ($requestedProvider !== '' && $requestedProvider !== $provider) {
            $this->sendJson(403, array('ok' => false, 'error' => 'ESP event handler: provider_not_active'));
        }

        $adapter = EspEventAdapterFactory::create($provider);
        if (!$adapter) {
            $this->sendJson(400, array('ok' => false, 'error' => 'ESP event handler: unsupported_provider'));
        }

        $rawBody = file_get_contents('php://input');
        if (!is_string($rawBody)) {
            $rawBody = '';
        }

        if (strlen($rawBody) > (1024 * 1024 * 2)) {
            $this->sendJson(413, array('ok' => false, 'error' => 'ESP event handler: payload_too_large'));
        }

        if (!$adapter->verifyRequest($_SERVER, $rawBody)) {
            error_log('MailBeez ESP webhook authentication failed for provider ' . $provider);
            $this->sendJson(401, array('ok' => false, 'error' => 'ESP event handler: unauthorized'));
        }

        $payload = $this->extractPayload($rawBody);
        $events = $this->extractEvents($payload);

        $stored = 0;
        $processed = 0;
        $failed = 0;
        foreach ($events as $item) {
            if (!is_array($item)) {
                continue;
            }

            $event = $adapter->normalizeEvent($item);
            $eventId = EspEventRepository::store($event);
            if ($eventId === null) {
                $failed++;
                continue;
            }

            $stored++;
            if (EspEventProcessor::process($eventId)) {
                $processed++;
            } else {
                $failed++;
            }
        }

        $this->sendJson(200, array(
            'ok' => true,
            'provider' => $provider,
            'stored' => $stored,
            'processed' => $processed,
            'failed' => $failed,
        ));
    }

    function sendJson($statusCode, array $body)
    {
        if (!headers_sent()) {
            header('Content-Type: application/json; charset=utf-8', true, (int)$statusCode);
        }

        echo json_encode($body);
        mh_exit();
    }

    function getConfiguredProvider()
    {
        $mailbeezEmailEngine = strtolower(trim((string)mh_cfg('MAILBEEZ_CONFIG_EMAIL_ENGINE', '')));
        if ($mailbeezEmailEngine === 'mlbz_hysndr') {
            return 'hysndr';
        }
        return '';
    }

    function normalizeProvider($provider)
    {
        return strtolower(trim((string)$provider));
    }

    function extractPayload($rawBody)
    {
        $payload = json_decode($rawBody, true);
        if (is_array($payload)) {
            return $payload;
        }

        if (isset($_POST['data'])) {
            $payload = json_decode(stripslashes((string)$_POST['data']), true);
            if (is_array($payload)) {
                return $payload;
            }
            return array('data' => $_POST['data']);
        }

        if (!empty($_POST) && is_array($_POST)) {
            return $_POST;
        }

        return array();
    }

    function extractEvents(array $payload)
    {
        if (isset($payload['events']) && is_array($payload['events'])) {
            return $payload['events'];
        }

        return array($payload);
    }
}
