<?php

declare(strict_types=1);

namespace Plugin\tnt_international_phone;

use JTL\Events\Dispatcher;
use JTL\Plugin\Bootstrapper;
use JTL\Shop;
use Plugin\tnt_international_phone\src\Admin\InvalidPhoneReport;
use Plugin\tnt_international_phone\src\Service\InvalidPhoneLogger;
use Plugin\tnt_international_phone\src\Service\ModifiedPhoneLogger;
use Plugin\tnt_international_phone\src\Service\PhoneSubmissionHandler;
use Plugin\tnt_international_phone\src\Service\PhoneValidator;
use Plugin\tnt_international_phone\src\Support\PhoneConfigBuilder;

class Bootstrap extends Bootstrapper
{
    public function boot(Dispatcher $dispatcher)
    {
        parent::boot($dispatcher);
        if (Shop::isFrontend() === false) {
            $this->handleAdminCsvExport();

            return;
        }
        $dispatcher->listen('shop.hook.' . \HOOK_LETZTERINCLUDE_INC, [$this, 'setConfig']);
        $this->handlePhoneSubmission($dispatcher);
    }

    /**
     * CSV export for the invalid-phone audit report (admin plugin page only).
     */
    private function handleAdminCsvExport(): void
    {
        $wantsInvalid  = isset($_GET['tnt_ip_export_csv']);
        $wantsModified = isset($_GET['tnt_ip_export_modified_csv']);
        if (!$wantsInvalid && !$wantsModified) {
            return;
        }
        $requestUri = $_SERVER['REQUEST_URI'] ?? '';
        $uri        = strtok($requestUri, '?');
        if ($uri !== '/admin/plugin/' . $this->getPlugin()->getID()) {
            return;
        }
        if (Shop::Container()->getAdminAccount()->logged() === false) {
            return;
        }
        $report = new InvalidPhoneReport($this->getDB());
        if ($wantsModified) {
            $report->streamModifiedCsv();
        }
        $report->streamCsv();
    }

    /**
     * Server-side E.164 validation: normalizes valid phone numbers in $_POST before the
     * shop controllers read them, rejects invalid ones via the core plausi hooks and
     * logs every invalid attempt to tnt_ip_invalid_phone.
     */
    private function handlePhoneSubmission(Dispatcher $dispatcher): void
    {
        if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') {
            return;
        }
        $autoload = __DIR__ . '/vendor/autoload.php';
        if (!\is_file($autoload)) {
            return; // fail open: without libphonenumber the plugin behaves as before
        }
        require_once $autoload;
        $config  = $this->getPlugin()->getConfig();
        $handler = new PhoneSubmissionHandler(
            new PhoneValidator($config->getValue('tnt_ip_phone_prefix') === 'yes'),
            new InvalidPhoneLogger($this->getDB()),
            new ModifiedPhoneLogger($this->getDB()),
            (string)$config->getValue('tnt_ip_default'),
            $config->getValue('tnt_ip_require_mobile') === 'yes'
        );
        $handler->process(
            $_POST,
            [PhoneSubmissionHandler::CONTEXT_ADDRESS, PhoneSubmissionHandler::CONTEXT_CONTACT]
        );
        if (!$handler->hasInvalid()) {
            return;
        }
        $markInvalid    = static function (array $args) use ($handler): void {
            foreach ($handler->getInvalidFields() as $field => $code) {
                $args['fehlendeAngaben'][$field] = $code;
            }
            $args['nReturnValue'] = false;
        };
        $rejectingHooks = [
            \HOOK_REGISTRIEREN_PAGE_REGISTRIEREN_PLAUSI,
            \HOOK_BESTELLVORGANG_INC_UNREGISTRIERTBESTELLEN_PLAUSI,
            \HOOK_BESTELLVORGANG_PAGE_STEPLIEFERADRESSE_NEUELIEFERADRESSE_PLAUSI,
        ];
        foreach ($rejectingHooks as $hook) {
            $dispatcher->listen('shop.hook.' . $hook, $markInvalid);
        }
        $dispatcher->listen(
            'shop.hook.' . \HOOK_JTL_PAGE_KUNDENDATEN_PLAUSI,
            static function (array $args): void {
                $args['returnCode'] = false;
            }
        );
    }

    public function setConfig(mixed $args): void
    {
        $smarty   = Shop::Smarty();
        $config   = $this->getPlugin()->getConfig();
        $locale   = $this->getPlugin()->getLocalization();
        $jsConfig = PhoneConfigBuilder::build(
            [
                'mobile_icon' => $config->getValue('tnt_ip_mobile_icon'),
                'phone_icon' => $config->getValue('tnt_ip_phone_icon'),
                'phone_prefix' => $config->getValue('tnt_ip_phone_prefix'),
                'default' => $config->getValue('tnt_ip_default'),
            ],
            $locale->getTranslations(),
        );
        $smarty->assign('tnt_ip_config', json_encode($jsConfig, JSON_THROW_ON_ERROR));
    }

    public function installed()
    {
        parent::installed();
    }

    public function updated($oldVersion, $newVersion)
    {
    }

    public function uninstalled(bool $deleteData = true)
    {
        parent::uninstalled($deleteData);
    }
}
