<?php
declare(strict_types=1);

namespace FiloBlu\ActiveCampaign\Helper;

use Exception;
use FiloBlu\ActiveCampaign\Helper\Data;
use FiloBlu\ConsentsManager\Api\ConsentSubscriptionRepositoryInterface;
use FiloBlu\ConsentsManager\Api\Data\ConsentSubscriptionInterface;
use FiloBlu\Esb\Model\QueueItemRepository;
use FiloBlu\Newsletter\Model\SubscriberInfoFactory;
use FiloBlu\Newsletter\Model\SubscriberInfoRepository;
use Magento\Customer\Model\CustomerFactory;
use Magento\Framework\App\Helper\AbstractHelper;
use Magento\Framework\App\Helper\Context;
use Magento\Framework\App\ResourceConnection;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\Serialize\SerializerInterface;
use Magento\Newsletter\Model\Subscriber;
use Magento\Newsletter\Model\SubscriberFactory;
use Magento\Sales\Model\ResourceModel\Order\CollectionFactory;
use Magento\Store\Api\Data\StoreInterface;
use Magento\Store\Model\ScopeInterface;
use Magento\Store\Model\StoreManagerInterface;

class ConsentsProfilingHelper extends AbstractHelper
{
    // Configurations constants
    const AC_MARKETING_CONSENTS_GENERAL_ENABLE = 'marketing_consents/general/enable';
    const AC_MARKETING_CONSENTS_TYPE = 'marketing_consents/general/consent_type';
    const AC_MARKETING_CONSENTS_CUSTOMER_MAP = 'marketing_consents/general/consents_customer_map';
    const AC_MARKETING_CONSENTS_GENERAL_REVOKE_AFTER_MONTHS = 'marketing_consents/general/revoke_after_months';

    // Option field used to map active campaign fields
    const MARKETING_PROFILE = 'marketing_profile';
    const MARKETING_PROFILE_SUBSCRIPTION_DATE = 'marketing_profile_subscription_date';
    const MARKETING_PROFILE_UNSUBSCRIPTION_DATE = 'marketing_profile_unsubscription_date';
    const MARKETING_PROFILE_ONLY_PROFILE = 'OnlyProfile';

    /**
     * @var SerializerInterface
     */
    private $serializer;
    /**
     * @var ConsentSubscriptionRepositoryInterface
     */
    private $consentSubscriptionRepository;
    /**
     * @var StoreManagerInterface
     */
    private $storeManager;
    /**
     * @var ResourceConnection
     */
    private $resourceConnection;
    /**
     * @var CustomerFactory
     */
    private $customerFactory;
    /**
     * @var SubscriberFactory
     */
    private $subscriberFactory;
    /**
     * @var CollectionFactory
     */
    private $orderCollectionFactory;
    /**
     * @var SubscriberInfoFactory
     */
    private $subscriberInfoFactory;
    /**
     * @var QueueItemRepository
     */
    private $queueItemRepository;
    /** @var \Magento\Framework\Module\Manager  */
    private $moduleManager;

    /**
     * @param SerializerInterface $serializer
     * @param ConsentSubscriptionRepositoryInterface $consentSubscriptionRepository
     * @param Context $context
     * @param StoreManagerInterface $storeManager
     * @param ResourceConnection $resourceConnection
     * @param CustomerFactory $customerFactory
     * @param SubscriberFactory $subscriberFactory
     * @param CollectionFactory $orderCollectionFactory
     * @param SubscriberInfoFactory $subscriberInfoFactory
     * @param QueueItemRepository $queueItemRepository
     */
    public function __construct(
        SerializerInterface                    $serializer,
        ConsentSubscriptionRepositoryInterface $consentSubscriptionRepository,
        Context                                $context,
        StoreManagerInterface                  $storeManager,
        ResourceConnection                     $resourceConnection,
        CustomerFactory                        $customerFactory,
        SubscriberFactory                      $subscriberFactory,
        CollectionFactory                      $orderCollectionFactory,
        SubscriberInfoFactory                  $subscriberInfoFactory,
        QueueItemRepository                    $queueItemRepository
    )
    {
        parent::__construct($context);
        $this->serializer = $serializer;
        $this->consentSubscriptionRepository = $consentSubscriptionRepository;
        $this->storeManager = $storeManager;
        $this->resourceConnection = $resourceConnection;
        $this->customerFactory = $customerFactory;
        $this->subscriberFactory = $subscriberFactory;
        $this->orderCollectionFactory = $orderCollectionFactory;
        $this->subscriberInfoFactory = $subscriberInfoFactory;
        $this->queueItemRepository = $queueItemRepository;
        $this->moduleManager = $context->getModuleManager();
    }

    /**
     * Check if functionality is enabled
     * @return mixed
     */
    public function isMarketingConsentsEnabled()
    {
        return $this->scopeConfig->getValue(
            self::AC_MARKETING_CONSENTS_GENERAL_ENABLE,
            ScopeInterface::SCOPE_STORE
        );
    }

    /**
     * Get Months Configuration for revoke a consents
     * The default value is set to 12 months
     * @return mixed|string
     */
    public function getRevokeAfterMonthConfiguration()
    {
        // 12 Month for revoke the consents
        $default = '12';

        $config = $this->scopeConfig->getValue(
            self::AC_MARKETING_CONSENTS_GENERAL_REVOKE_AFTER_MONTHS,
            ScopeInterface::SCOPE_STORE
        );

        return $config ?: $default;
    }

    /**
     * Add Consent Data to Request Array
     * @param $result
     * @param $email
     * @return array
     */
    public function addConsentDataToRequest($result, $email): array
    {

        if (!$this->isConsentsManagerEnabled()) {
            return $result;
        }

        $customerSubscription = $this->getConsentsSubscriptionData($email);

        if (!$customerSubscription) {
            return $result;
        }

        $isSubscribed = false;

        $fieldsMap = [];
        $subscriber = $this->loadSubscriberByEmail($email);

        if ($subscriber) {
            $subscriberInfo = $this->subscriberInfoFactory->create()->load($subscriber->getId());

            $order = $this->getEmailLastOrder($email);

            if ($subscriber->toArray() && $subscriber->getSubscriberStatus() == 1) {
                $isSubscribed = true;
            }
        }

        $fieldsMap = [
            self::MARKETING_PROFILE => [
                'method' => 'getRevokedAt',
                'valueCallback' => function ($value) {
                    return $value ? '--' : 'TRUE'; // Invio come stringhe come richiesto dal reparto DEM
                }
            ],
            self::MARKETING_PROFILE_SUBSCRIPTION_DATE => [
                'method' => 'getAcceptedAt',
                'valueCallback' => function ($value) {
                    return $value ?: '';
                }
            ],
            self::MARKETING_PROFILE_UNSUBSCRIPTION_DATE => [
                'method' => 'getRevokedAt',
                'valueCallback' => function ($value) {
                    return $value ?: '';
                }
            ]
        ];

        return $this->processFieldsMap($fieldsMap, $customerSubscription, $result);
    }

    /**
     * Get Consents Subscription Data
     * @param $email
     * @return false|ConsentSubscriptionInterface
     */
    public function getConsentsSubscriptionData($email)
    {
        if (!$this->getConsentTypeConfiguration()) {
            return false;
        }

        try {
            $consentSubscription = $this->consentSubscriptionRepository->retrieveByEmailAndType($email, $this->getConsentTypeConfiguration());
        } catch (NoSuchEntityException $ex) {
            return false;
        }

        return $consentSubscription;
    }

    /**
     * Get Consent Type Configuration
     * @return mixed
     */
    public function getConsentTypeConfiguration()
    {
        return $this->scopeConfig->getValue(
            self::AC_MARKETING_CONSENTS_TYPE,
            ScopeInterface::SCOPE_STORE
        );
    }



    public function loadSubscriberByEmail(string $email)
    {
        // Usa il factory per creare un'istanza del modello Subscriber
        $subscriber = $this->subscriberFactory->create();
        $subscriber->loadByEmail($email);

        // Controlla se il subscriber esiste
        if (!$subscriber->getId()) {
            return null; // Nessun subscriber trovato
        }

        return $subscriber;
    }

    public function getEmailLastOrder($email)
    {
        try {
            return $this->orderCollectionFactory->create()
                ->addAttributeToFilter('customer_email', $email)->getLastItem();
        } catch (Exception $e) {
            return false;
        }
    }

    public function processFieldsMap($fieldsMap, $customerSubscription, $result)
    {
        foreach ($fieldsMap ?? [] as $constant => $config) {
            $fieldId = $this->getActiveCampaignFieldId($constant);

            if ($fieldId) {
                $method = $config['method'];

                if (!empty($config['valueCallback'])) {
                    $value = $customerSubscription->$method();
                    $fieldValue = $config['valueCallback']($value);
                }

                if (array_key_exists('value', $config)) {
                    $fieldValue = $config['value'];
                }

                $result['create_update_contact']['request']['contact']['fieldValues'][] = [
                    "field" => $fieldId,
                    "value" => $fieldValue
                ];
            }
        }

        return $result;
    }

    /**
     * Retrieve Active Campaign Field ID from consent field constant
     *
     * @param string $consentField One of the defined constants (MARKETING_PROFILE, MARKETING_PROFILE_SUBSCRIPTION_DATE, MARKETING_PROFILE_UNSUBSCRIPTION_DATE)
     * @return string|null Active Campaign Field ID or null if not found
     */
    public function getActiveCampaignFieldId($consentField)
    {
        $configsMap = $this->getConsentsCustomerMapData();

        foreach ($configsMap as $config) {
            if (isset($config['consents_field']) && $config['consents_field'] === $consentField) {
                return $config['active_campaign_field'];
            }
        }

        return null;
    }

    /**
     * Return mapped configuration
     * @return array|bool|float|int|string|null
     */
    public function getConsentsCustomerMapData()
    {
        $configValue = $this->scopeConfig->getValue(
            self::AC_MARKETING_CONSENTS_CUSTOMER_MAP,
            ScopeInterface::SCOPE_STORE
        );

        try {
            return $this->serializer->unserialize($configValue);
        } catch (Exception $e) {
            return [];
        }
    }

    /**
     * Set Current Store form Subscriber ID
     * @param $entityId
     * @return StoreInterface
     * @throws NoSuchEntityException
     */
    public function setStoreFromSubscriberId($entityId): StoreInterface
    {
        $currentStore = $this->storeManager->getStore();
        $connection = $this->resourceConnection->getConnection();
        $tableName = $this->resourceConnection->getTableName('newsletter_subscriber');
        $sql = $connection->select()
            ->from($tableName, ['store_id'])
            ->where('subscriber_id = ?', $entityId);
        $storeId = $connection->fetchOne($sql);
        $this->storeManager->setCurrentStore($storeId);
        return $currentStore;
    }

    /**
     * Set Current Store form Customer ID
     * @param $entityId
     * @return StoreInterface
     * @throws NoSuchEntityException
     */
    public function setStoreFromCustomerId($entityId): StoreInterface
    {
        $currentStore = $this->storeManager->getStore();
        $connection = $this->resourceConnection->getConnection();
        $tableName = $this->resourceConnection->getTableName('customer_entity');
        $sql = $connection->select()
            ->from($tableName, ['store_id'])
            ->where('entity_id = ?', $entityId);
        $storeId = $connection->fetchOne($sql);
        $this->storeManager->setCurrentStore($storeId);
        return $currentStore;
    }

    /**
     * Restore Store
     * @param $oldStore
     * @return void
     */
    public function restoreStore($oldStore)
    {
        $this->storeManager->setCurrentStore($oldStore);
    }

    public function getCustomerByEmail($email)
    {
        try {
            $subscriber = $this->subscriberFactory->create()->load($email, 'subscriber_email');
            $storeId = $subscriber->getStoreId();
            $websiteId = $this->storeManager->getStore($storeId)->getWebsiteId();
            return $this->customerFactory->create()->setWebsiteId($websiteId)->loadByEmail($email);
        } catch (Exception $e) {
            return false;
        }
    }

    public function getFiloBluSubscriberInfo($subscriberId)
    {
        return $this->subscriberInfoFactory->create()->load($subscriberId);
    }

    public function isConsentsManagerEnabled(): bool
    {
        return $this->moduleManager->isEnabled('FiloBlu_ConsentsManager');
    }

}
