<?php

declare(strict_types=1);

namespace MauticPlugin\DealFlowBundle\EventSubscriber;

use Mautic\ConfigBundle\ConfigEvents;
use Mautic\ConfigBundle\Event\ConfigBuilderEvent;
use Mautic\ConfigBundle\Event\ConfigEvent;
use MauticPlugin\DealFlowBundle\Form\Type\DealFlowConfigType;
use MauticPlugin\DealFlowBundle\Service\IntegrityService;
use MauticPlugin\DealFlowBundle\Service\LicenseService;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface;

/**
 * Registers Deal Flow settings in Mautic's Configuration page.
 * Also handles license activation when a key is entered here.
 */
final class ConfigSubscriber implements EventSubscriberInterface
{
    public function __construct(
        private readonly LicenseService $licenseService,
        private readonly RequestStack $requestStack,
        private readonly IntegrityService $integrityService,
    ) {
    }

    /**
     * @return array<string, string>
     */
    public static function getSubscribedEvents(): array
    {
        return [
            ConfigEvents::CONFIG_ON_GENERATE => 'onConfigGenerate',
            ConfigEvents::CONFIG_PRE_SAVE => 'onConfigPreSave',
        ];
    }

    public function onConfigGenerate(ConfigBuilderEvent $event): void
    {
        $event->addForm([
            'bundle' => 'DealFlowBundle',
            'formAlias' => 'dealflow_config',
            'formType' => DealFlowConfigType::class,
            'parameters' => [
                'dealflow_default_association_labels' => [
                    'Decision Maker',
                    'Billing Contact',
                    'Champion',
                    'Legal',
                ],
                'dealflow_default_sources' => [
                    'Inbound marketing',
                    'Outbound prospecting',
                    'Referral',
                    'Partner',
                    'Event',
                    'Website',
                    'Existing customer',
                    'Manual',
                ],
                'dealflow_inbound_webhook_secret' => '',
                'dealflow_default_currency' => 'USD',
                'dealflow_items_per_page' => 30,
                'dealflow_health_yellow_days' => 7,
                'dealflow_health_red_days' => 14,
                'dealflow_default_task_priority' => 'normal',
                'dealflow_license_key' => '',
                'dealflow_license_status' => 'not_configured',
                'dealflow_license_updates_until' => '',
                'dealflow_license_last_validated_at' => '',
                'dealflow_license_last_validation_valid' => '',
                'dealflow_license_hash' => '',
                'dealflow_file_checksum' => '',
            ],
        ]);
    }

    public function onConfigPreSave(ConfigEvent $event): void
    {
        /** @var array<string, mixed>|null $data */
        $data = $event->getConfig('dealflow_config');
        if (!\is_array($data)) {
            return;
        }

        $newKey = (string) ($data['dealflow_license_key'] ?? '');
        $storedKey = $this->licenseService->getCurrentKey() ?? '';

        // Handle masked key submission — user didn't change the key
        if (str_contains($newKey, '****')) {
            $data['dealflow_license_key'] = $storedKey;
            $event->setConfig($data, 'dealflow_config');

            return;
        }

        // Key cleared — reset status
        if ($newKey === '') {
            $data['dealflow_license_status'] = 'not_configured';
            $data['dealflow_license_updates_until'] = '';
            $data['dealflow_license_last_validated_at'] = '';
            $data['dealflow_license_last_validation_valid'] = '';
            $data['dealflow_license_hash'] = '';
            $data['dealflow_file_checksum'] = '';
            $this->licenseService->clearValidationCache();
            $event->setConfig($data, 'dealflow_config');

            return;
        }

        // Skip if key unchanged and already active
        if ($newKey === $storedKey && $this->licenseService->getStatus() === 'active') {
            return;
        }

        // Activate the license
        $result = $this->licenseService->activate($newKey);

        $data['dealflow_license_status'] = $result->valid ? 'active' : 'invalid';
        $data['dealflow_license_last_validated_at'] = (new \DateTimeImmutable())->format('c');
        $data['dealflow_license_last_validation_valid'] = $result->valid ? '1' : '';

        if ($result->updatesUntil !== null) {
            $data['dealflow_license_updates_until'] = $result->updatesUntil;
        }

        // Generate integrity hash and file checksum on success
        if ($result->valid) {
            $subdomain = $this->licenseService->getSubdomain();
            if ($subdomain !== null) {
                $data['dealflow_license_hash'] = $this->integrityService->generateLicenseHash($newKey, $subdomain);
                $data['dealflow_file_checksum'] = $this->integrityService->calculateFileChecksum();
            }
        } else {
            $data['dealflow_license_hash'] = '';
            $data['dealflow_file_checksum'] = '';
        }

        $this->licenseService->clearValidationCache();
        $event->setConfig($data, 'dealflow_config');

        // Flash the result
        $flashBag = $this->getFlashBag();
        if ($flashBag !== null) {
            if ($result->valid) {
                $flashBag->add('notice', 'Deal Flow: '.$result->message);
            } elseif ($result->apiUnreachable) {
                $flashBag->add('warning', 'Deal Flow: '.$result->message);
            } else {
                $flashBag->add('error', 'Deal Flow: '.$result->message);
            }
        }
    }

    private function getFlashBag(): ?FlashBagInterface
    {
        $session = $this->requestStack->getMainRequest()?->getSession();
        if ($session instanceof \Symfony\Component\HttpFoundation\Session\Session) {
            return $session->getFlashBag();
        }

        return null;
    }
}
