<?php

declare(strict_types=1);

namespace FiloBlu\Refilo\Plugins\Api;

use FiloBlu\Newsletter\Model\SubscriberInfo;
use Magento\Customer\Api\Data\CustomerInterface;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\Module\Manager;
use Magento\Framework\ObjectManagerInterface;
use Magento\Framework\Webapi\Rest\Request;
use Magento\Newsletter\Model\Subscriber;
use Magento\Newsletter\Model\SubscriberFactory;
use Magento\Store\Api\Data\StoreInterface;
use Magento\Store\Model\ScopeInterface;
use Magento\Store\Model\StoreManagerInterface;
use Psr\Log\LoggerInterface;
use Throwable;

/**
 * Class CustomerRepositoryInterface
 * @package FiloBlu\Refilo\Plugins\Api
 */
class CustomerRepositoryInterface
{
    /**
     * @var string
     */
    const DEFAULT_SOURCE = 'ACCOUNT';
    /**
     * @var StoreManagerInterface
     */
    private $storeManager;

    /**
     * @var SubscriberFactory
     */
    private $subscriberFactory;

    /**
     * @var ObjectManagerInterface
     */
    private $objectManager;

    /**
     * @var Manager
     */
    private $moduleManager;

    /**
     * @var ScopeConfigInterface
     */
    private $scopeConfig;

    /**
     * @var LoggerInterface
     */
    private $logger;

    /**
     * CustomerRepositoryInterface constructor.
     * @param StoreManagerInterface $storeManager
     * @param SubscriberFactory $subscriberFactory
     * @param ObjectManagerInterface $objectManager
     * @param Manager $moduleManager
     * @param ScopeConfigInterface $scopeConfig
     * @param LoggerInterface $logger
     */
    public function __construct(
        StoreManagerInterface $storeManager,
        SubscriberFactory $subscriberFactory,
        ObjectManagerInterface $objectManager,
        Manager $moduleManager,
        ScopeConfigInterface $scopeConfig,
        LoggerInterface $logger
    ) {
        $this->storeManager = $storeManager;
        $this->subscriberFactory = $subscriberFactory;
        $this->objectManager = $objectManager;
        $this->moduleManager = $moduleManager;
        $this->scopeConfig = $scopeConfig;
        $this->logger = $logger;
    }

    /**
     * @param \Magento\Customer\Api\CustomerRepositoryInterface $subject
     * @param CustomerInterface $customer
     * @param CustomerInterface $customerRequest
     * @return CustomerInterface
     */
    public function afterSave(\Magento\Customer\Api\CustomerRepositoryInterface $subject, $customer, CustomerInterface $customerRequest)
    {
        if (!$this->moduleManager->isEnabled('FiloBlu_Newsletter')) {
            return $customer;
        }

        try {
            $this->addSubscriberInfo($customer, $customerRequest);
        } catch (Throwable $throwable) {
            $this->logger->error($throwable->getMessage(), ['exception' => $throwable]);
        }

        return $customer;
    }

    /**
     * @param CustomerInterface $customer
     * @param CustomerInterface $customerRequest
     * @return CustomerInterface
     * @throws LocalizedException
     * @throws NoSuchEntityException
     */
    public function addSubscriberInfo(CustomerInterface $customer, CustomerInterface $customerRequest)
    {
        /** @var CustomerInterface $customer */
        /** @var Subscriber $subscriber */
        $subscriber = $this->getSubscriberFromMethodSwitch($customer);


        if (!$subscriber->getId()) {
            return $customer;
        }

        /** @var SubscriberInfo $subscrberInfo */
        $subscrberInfo = $this->objectManager->create(SubscriberInfo::class);

        $subscrberInfo->load((int)$subscriber->getId(), 'subscriber_id');

        $website = $this->storeManager->getWebsite($customer->getWebsiteId());
        $store = $this->storeManager->getStore($customer->getStoreId());

        $subscrberInfo->addData([
            'subscriber_id' => $subscriber->getId(),
            'source'        => $this->getSource($customerRequest, $subscrberInfo),
            'email'         => $customer->getEmail(),
            'firstname'     => $customer->getFirstname(),
            'lastname'      => $customer->getLastname(),
            'dob'           => $customer->getDob(),
            'gender'        => $customer->getGender(),
            'language'      => $this->getLanguage($customerRequest, $subscrberInfo, $store),
            'type'          => 'CUSTOMER',
            'website_name'  => $website->getName(),
            'country'       => $this->getCountry($customer, $customerRequest, $subscrberInfo),
            // 'collections'   => $collections,
            // 'phone'         => $phone,
            // 'birthday'      => $birthday
        ]);

        $subscrberInfo->save();
    }

    /**
     * @param CustomerInterface $customerRequest
     * @param SubscriberInfo $subscriberInfo
     * @return array|mixed|string
     */
    public function getSource(CustomerInterface $customerRequest, SubscriberInfo $subscriberInfo)
    {
        $originalSource = $subscriberInfo->getData('source');

        if (!$customerRequest->getExtensionAttributes()) {
            return $originalSource ?: self::DEFAULT_SOURCE;
        }

        $source = $customerRequest->getExtensionAttributes()->getFilobluNewsletterSource();

        if ($source) {
            return trim(strtoupper($source));
        }

        return $originalSource ?: self::DEFAULT_SOURCE;
    }

    /**
     * @param CustomerInterface $customerRequest
     * @param SubscriberInfo $subscriberInfo
     * @param StoreInterface $store
     * @return array|mixed
     */
    public function getLanguage(CustomerInterface $customerRequest, SubscriberInfo $subscriberInfo, StoreInterface $store)
    {
        $language = $this->scopeConfig->getValue('general/locale/code', ScopeInterface::SCOPE_STORE, $store->getCode());

        $originalLanguage = $subscriberInfo->getData('language');

        if (!$originalLanguage) {
            return $language;
        }

        return $originalLanguage;
    }

    /**
     * @param CustomerInterface $customer
     * @param CustomerInterface $customerRequest
     * @param SubscriberInfo $subscriberInfo
     * @return array|mixed|null
     */
    public function getCountry(CustomerInterface $customer, CustomerInterface $customerRequest, SubscriberInfo $subscriberInfo)
    {
        $originalCountry = $subscriberInfo->getData('country');

        if ($originalCountry) {
            return $originalCountry;
        }

        $countries = [];

        foreach ($customer->getAddresses() ?? [] as $address) {
            $countryId = $address->getCountryId();

            if (!isset($countries[$countryId])) {
                $countries[$countryId] = 1;
                continue;
            }

            $countries[$countryId] += 1;
        }

        if (empty($countries)) {
            return null;
        }

        $countries = array_flip($countries);

        ksort($countries);

        return array_shift($countries);
    }

    /**
     * @param CustomerInterface $customer
     * @return Subscriber
     */
    public function getSubscriberFromMethodSwitch(CustomerInterface $customer)
    {
        $subscriberFactoryInstance = $this->subscriberFactory->create();

        //@ToDo Backward compatibility issue from Magento 2.4 fix
        if (method_exists ( $subscriberFactoryInstance, 'loadByCustomerId')) {
            return $subscriberFactoryInstance->loadByCustomerId((int)$customer->getId());
        }

        return $subscriberFactoryInstance->loadByCustomer((int)$customer->getId(), (int)$customer->getWebsiteId());
    }
}
