<?php

namespace Benhauer\Salesmanago\Model;

use \Magento\Framework\Model\AbstractModel as MagentoAbstractModel;
use \Magento\Framework\Model\Context;
use \Magento\Framework\Registry;
use \Magento\Customer\Api\CustomerRepositoryInterface;
use \Magento\Newsletter\Model\Subscriber;
use \Magento\Directory\Api\CountryInformationAcquirerInterface;

use \Benhauer\Salesmanago\Model\Hooks as HooksModel;
use \Benhauer\Salesmanago\Helper\Contact\Contact as SmContact;
use \Benhauer\Salesmanago\Helper\Contact\Address as SmContactAddress;
use \Benhauer\Salesmanago\Helper\Contact\Options as SmContactOptions;

class Contact extends MagentoAbstractModel
{
    public $Contact;
    public $Address;
    public $Options;
    public $logger;
    public $subscriber;

    public function __construct(
        Context $context,
        Registry $registry,
        SmContact $Contact,
        SmContactAddress $Address,
        SmContactOptions $Options,
        CustomerRepositoryInterface $customerRepositoryInterface,
        Subscriber $subscriber,
        CountryInformationAcquirerInterface $countryInformation
    ) {
        parent::__construct(
            $context,
            $registry
        );

        $this->customerRepositoryInterface = $customerRepositoryInterface;
        $this->Contact = $Contact;
        $this->Address = $Address;
        $this->Options = $Options;
        $this->logger  = $context->getLogger();
        $this->subscriber = $subscriber;
        $this->countryInformation = $countryInformation;
    }

    /**
     * @param int $customerId
     * @return SmContact
     * @throws \Exception
     */
    public function getContactByCustomerId($customerId)
    {
        try {
            $customer = $this->customerRepositoryInterface->getById($customerId);

            if (method_exists($customer, 'getDefaultBillingAddress')) {
                $customerAddress = $customer->getDefaultBillingAddress();
            } else {
                $customerAddresses = $customer->getAddresses();
                //get only last address in array
                foreach ($customerAddresses as $address) {
                    $customerAddress = $address;
                }
            }

            $email = $customer->getEmail();
            $name = [
                $customer->getFirstname(),
                $customer->getMiddlename(),
                $customer->getLastname()
            ];

            $phone = method_exists($customer, 'getTelephone') ? $customer->getTelephone() : '';
            $fax = method_exists($customer, 'getFax') ? $customer->getFax() : '';
            $company = method_exists($customer, 'getCompany') ? $customer->getCompany() : '';
            $externalId = method_exists($customer, 'getId') ? $customer->getId() : '';

            $street = '';
            $postcode = '';
            $city = '';
            $country = '';

            if (!empty($customerAddress)) {
                $street = method_exists($customerAddress, 'getStreet')
                    ? $customerAddress->getStreet()
                    : $street;
                $postcode = method_exists($customerAddress, 'getPostcode')
                    ? $customerAddress->getPostcode()
                    : $postcode;
                $city = method_exists($customerAddress, 'getCity')
                    ? $customerAddress->getCity()
                    : $city;
                $country = method_exists($customerAddress, 'getCountry')
                    ? $customerAddress->getCountry()
                    : (
                method_exists($customerAddress, 'getCountryId')
                    ? $customerAddress->getCountryId()
                    : $country
                );

                $phone = (empty($phone) && method_exists($customerAddress, 'getTelephone'))
                    ? $customerAddress->getTelephone()
                    : $phone;

                $fax = (empty($fax) && method_exists($customerAddress, 'getFax'))
                    ? $customerAddress->getFax()
                    : $fax;

                $company = (empty($company) && method_exists($customerAddress, 'getCompany'))
                    ? $customerAddress->getCompany()
                    : $company;
            }

            $dob = ($customer->getDob()) ? date('Ymd', strtotime($customer->getDob())) : '';

            $createdOn = method_exists($customer, 'getCreatedAt')
                ? $customer->getCreatedAt()
                : date("F j, Y, g:i a", time());

            $this->Contact->set(
                $email,
                '',
                $name,
                $phone,
                $fax,
                $company,
                '',
                $externalId
            );

            $Address = $this->Address->set(
                $street,
                $postcode,
                $city,
                $country
            );

            $Options = $this->Options->set(
                '',
                '',
                $dob,
                false,
                true,
                '',
                '',
                '',
                ''
                )->setAdditional(
                    ['createdOn' => $createdOn]
            );

            $this->Contact->setAddress($Address);
            $this->Contact->setOptions($Options);
            $this->_setContactOptStatus();
            return $this->Contact;
        } catch (\Exception $e) {
            $this->logger->critical($e->getMessage());
        }
    }

    /**
     * @param object $billingAddress magento billing addess
     * @param string $customerEmail - contact email
     * @return SmContact
     * @throws \Exception
     */
    public function getContactByCustomerBillingAddress($billingAddress, $customerEmail)
    {
        $this->Options->setAdditional(
            [
                'province' => $billingAddress->getRegion(),
                'createdOn' => date('c')
            ]
        );

        $this->Address->set(
            $billingAddress->getStreet(),
            $billingAddress->getPostCode(),
            $billingAddress->getCity(),
            $this->_getCountryNameByCode($billingAddress->getCountryId())
        );

        $this->Contact->set(
            $customerEmail,
            '',
            [
                $billingAddress->getFirstname(),
                $billingAddress->getLastname()
            ],
            $billingAddress->getTelephone(),
            $billingAddress->getFax(),
            $billingAddress->getCompany(),
            '',
            ''
        );

        $this->Contact
            ->setAddress($this->Address)
            ->setOptions($this->Options);

        $this->_setContactOptStatus();

        return $this->Contact;
    }

    /**
     * Sets Opt States for Contact object base on magento subscriber status
     *
     * @param string $email - contact email;
     * @param string $customerId - external contact id;
     * @return object $this->Contact;
    */
    private function _setContactOptStatus($email = '', $customerId = '')
    {
        try {
            $subscriber = false;

            if (!empty($email)) {
                $subscriber = $this->subscriber->loadByEmail($email);
            }

            if (!$subscriber && $this->Contact->getEmail()) {
                $subscriber = $this->subscriber->loadByEmail($this->Contact->getEmail());
            }

            if (!empty($customerId) && !$subscriber) {
                $subscriber = $this->subscriber->loadByCustomerId($customerId);
            }

            if ($subscriber && $subscriber->isSubscribed()) {
                $this->Contact
                    ->getOptions()
                    ->setForceOptIn(true)
                    ->setForcePhoneOptIn(true)
                    ->setForcePhoneOptOut(false);
            } else {
                $this->Contact
                    ->getOptions()
                    ->setForceOptIn(false)
                    ->setForceOptOut(true)
                    ->setForcePhoneOptIn(false)
                    ->setForcePhoneOptOut(true);
            }

            return $this->Contact;
        } catch (\Exception $e) {
            $this->logger->critical($e->getMessage());
        }
    }

    /**
     * @param string $countryId coutry short code such EN, PL, DE, etc.;
     * @return string full country name;
     * @log Exception to magento log file;
    */
    private function _getCountryNameByCode($countryId)
    {
        try {
            if ($countryId == null) {
                return '';
            }

            return $this->countryInformation
                ->getCountryInfo($countryId)
                ->getFullNameLocale();
        } catch (\Exception $e) {
            $this->logger->critical($e->getMessage());
        }
    }
}
