<?php

declare(strict_types=1);

namespace MauticPlugin\DealFlowBundle\EventSubscriber;

use Mautic\PluginBundle\Event\PluginIntegrationEvent;
use Mautic\PluginBundle\Helper\IntegrationHelper;
use Mautic\PluginBundle\PluginEvents;
use MauticPlugin\DealFlowBundle\Integration\DealFlowIntegration;
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\Session;

/**
 * Handles license activation when the Deal Flow plugin popup is saved.
 */
final class IntegrationConfigSubscriber implements EventSubscriberInterface
{
    public function __construct(
        private readonly LicenseService $licenseService,
        private readonly IntegrityService $integrityService,
        private readonly IntegrationHelper $integrationHelper,
        private readonly RequestStack $requestStack,
    ) {
    }

    /**
     * @return array<string, string>
     */
    public static function getSubscribedEvents(): array
    {
        return [
            PluginEvents::PLUGIN_ON_INTEGRATION_CONFIG_SAVE => 'onConfigSave',
        ];
    }

    public function onConfigSave(PluginIntegrationEvent $event): void
    {
        $entity = $event->getEntity();
        if ('DealFlow' !== $entity->getName()) {
            return;
        }

        // Get the integration object — it has the NEW plaintext keys
        // (encryptAndSetApiKeys was already called by the controller)
        $integration = $this->integrationHelper->getIntegrationObject('DealFlow');
        if (!$integration instanceof DealFlowIntegration) {
            return;
        }

        $keys = $integration->getKeys();
        $licenseKey = $keys['license_key'] ?? '';

        /** @var array<string, mixed> $featureSettings */
        $featureSettings = $entity->getFeatureSettings() ?? [];

        // Key cleared — reset status
        if ($licenseKey === '') {
            $featureSettings['license_status'] = 'not_configured';
            $featureSettings['license_updates_until'] = '';
            $featureSettings['license_hash'] = '';
            $featureSettings['file_checksum'] = '';
            $featureSettings['license_last_validated_at'] = '';
            $featureSettings['license_last_validation_valid'] = '';
            $entity->setFeatureSettings($featureSettings);
            $this->licenseService->clearValidationCache();

            return;
        }

        // Activate the license (API is idempotent for same key+subdomain)
        $result = $this->licenseService->activate($licenseKey);

        $featureSettings['license_status'] = $result->valid ? 'active' : 'invalid';
        $featureSettings['license_last_validated_at'] = (new \DateTimeImmutable())->format('c');
        $featureSettings['license_last_validation_valid'] = $result->valid;

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

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

        $entity->setFeatureSettings($featureSettings);
        $this->licenseService->clearValidationCache();

        // Flash the result
        $session = $this->requestStack->getMainRequest()?->getSession();
        if ($session instanceof Session) {
            if ($result->valid) {
                $session->getFlashBag()->add('notice', 'Deal Flow: '.$result->message);
            } elseif ($result->apiUnreachable) {
                $session->getFlashBag()->add('warning', 'Deal Flow: '.$result->message);
            } else {
                $session->getFlashBag()->add('error', 'Deal Flow: '.$result->message);
            }
        }
    }
}
