<?php

declare(strict_types=1);

namespace FiloBlu\Refilo\Model\Importer;

use FiloBlu\Core\Model\Configuration;
use FiloBlu\Refilo\Model\Adapter\Mongo;
use FiloBlu\Refilo\Model\WishlistManagement;
use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Catalog\Model\Product\Type;
use Magento\ConfigurableProduct\Model\Product\Type\Configurable;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\App\ResourceConnection;
use Magento\Framework\Exception\NoSuchEntityException;
use Symfony\Component\Console\Input\InputInterface;

/**
 * @class Wishlist
 * @package FiloBlu\Refilo\Model\Importer
 */
class Wishlist extends AbstractImporter
{

    /** @var ResourceConnection */
    private $connection;
    /** @var WishlistManagement */
    private $wishlistManagement;
    /** @var ProductRepositoryInterface */
    private $productRepository;
    /** @var Configurable */
    private $configurable;

    /**
     * @param Mongo $mongo
     * @param Configuration $coreConfiguration
     * @param ScopeConfigInterface $scopeConfig
     * @param ResourceConnection $connection
     * @param WishlistManagement $wishlistManagement
     * @param ProductRepositoryInterface $productRepository
     * @param Configurable $configurable
     */
    public function __construct(
        Mongo                      $mongo,
        Configuration              $coreConfiguration,
        ScopeConfigInterface       $scopeConfig,
        ResourceConnection         $connection,
        WishlistManagement         $wishlistManagement,
        ProductRepositoryInterface $productRepository,
        Configurable               $configurable
    ) {
        parent::__construct(
            $mongo,
            $coreConfiguration,
            $scopeConfig
        );
        $this->scopeConfig = $scopeConfig;
        $this->connection = $connection;
        $this->wishlistManagement = $wishlistManagement;
        $this->productRepository = $productRepository;
        $this->configurable = $configurable;
    }

    public function preExecute(InputInterface $input = null)
    {
        // Intentionally left blank
    }

    /**
     * @return iterable
     */
    public function getCollections(): iterable
    {
        yield 'wishlist';
    }

    /**
     * @param InputInterface|null $input
     */
    public function execute(InputInterface $input = null)
    {
        for ($customerId = 1; $customerId <= $this->getMaxCustomerId(); $customerId++) {
            $wishlist = $this->getConnection()->getById('wishlist', (string) $customerId);
            if ($wishlist) {
                $this->deleteCustomerWishlist($customerId);

                $wishlistItems = $wishlist['items'];
                foreach ($wishlistItems as $item) {
                    try {
                        try {
                            $product = $this->productRepository->get($item['sku']);
                        } catch (NoSuchEntityException $exception) {
                            $product = null;
                        }

                        if ($product === null) {
                            continue;
                        }

                        if ($product->getTypeId() === Type::TYPE_SIMPLE) {
                            $parentIds = array_values($this->configurable->getParentIdsByChild($product->getId()));
                            if (empty($parentIds)) {
                                continue;
                            }

                            $parentId = array_shift($parentIds);
                            if ($parentId) {
                                $this->wishlistManagement->saveProductToWishlist((int)$parentId, $customerId);
                            }

                            continue;
                        }
                        $this->wishlistManagement->saveProductToWishlist((int)$product->getId(), $customerId);
                    } catch (\Exception $e) {
                        // probably missing customer
                        continue;
                    }
                }
            }
        }
    }

    /**
     * @return int
     */
    public function getMaxCustomerId()
    {
        $connection = $this->connection->getConnection();
        $maxIdObj = $connection->fetchOne('SELECT entity_id FROM customer_entity ORDER BY entity_id DESC LIMIT 0, 1');

        return (int)$maxIdObj;
    }

    /**
     * @param string|null $sku
     * @return ProductInterface|null
     */
    public function loadProductBySku(?string $sku)
    {
        try {
            return $this->productRepository->get($sku);
        } catch (NoSuchEntityException $exception) {
            return null;
        }
    }

    /**
     * @param int $customerId
     * @return bool
     */
    public function customerExists(int $customerId)
    {
        $connection = $this->connection->getConnection();
        $customer = $connection->fetchOne('SELECT entity_id FROM customer_entity WHERE entity_id = ? ', [$customerId]);

        return (bool)$customer;
    }

    /**
     * @param InputInterface|null $input
     * @return void
     */
    public function postExecute(InputInterface $input = null)
    {
        // Intentionally left blank
    }

    /**
     * @param int $customerId
     * @return void
     */
    public function deleteCustomerWishlist(int $customerId)
    {
        // wishlist cleaning through WishlistManagement seems to be not working occasionally
        $connection = $this->connection->getConnection();
        $connection->query("DELETE FROM wishlist WHERE customer_id={$customerId};");
    }
}
