<?php

namespace FiloBlu\Refilo\Model;

use FiloBlu\Refilo\Api\WishlistManagementInterface;
use Magento\Authorization\Model\UserContextInterface;
use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Framework\DataObjectFactory;
use Magento\Framework\Exception\AlreadyExistsException;
use Magento\Framework\Exception\AuthorizationException;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Wishlist\Model\ResourceModel\Wishlist;
use Magento\Wishlist\Model\WishlistFactory;

/**
 *
 */
class WishlistManagement implements WishlistManagementInterface
{
    /** @var WishlistFactory */
    protected $wishlistFactory;

    /** @var Wishlist */
    protected $wishlistResource;

    /** @var ProductRepositoryInterface */
    protected $productRepository;
    /**
     * @var DataObjectFactory
     */
    private $objectFactory;

    /** @var UserContextInterface */
    private $userContext;


    public function __construct(
        WishlistFactory $wishlistFactory,
        Wishlist $wishlistResource,
        ProductRepositoryInterface $productRepository,
        DataObjectFactory $objectFactory,
        UserContextInterface $userContext
    ) {
        $this->wishlistFactory = $wishlistFactory;
        $this->wishlistResource = $wishlistResource;
        $this->productRepository = $productRepository;
        $this->objectFactory = $objectFactory;
        $this->userContext = $userContext;
    }

    /**
     * Resolve the customer id from the authenticated token, ignoring any client-supplied id.
     *
     * Prevents IDOR: the wishlist always belongs to the logged-in customer, never to an
     * arbitrary customer_id passed in the request.
     *
     * @return int
     * @throws AuthorizationException
     */
    private function resolveCustomerId(): int
    {
        $tokenCustomerId = (int)$this->userContext->getUserId();
        if ($this->userContext->getUserType() !== UserContextInterface::USER_TYPE_CUSTOMER || !$tokenCustomerId) {
            throw new AuthorizationException(__('You are not allowed to access this wishlist.'));
        }
        return $tokenCustomerId;
    }


    /**
     * @param int $productId
     * @param int $customerId
     * @param mixed $attributeId
     * @param mixed $optionValue
     * @return void
     * @throws AlreadyExistsException
     * @throws LocalizedException
     */
    public function saveProductToWishlist(int $productId, int $customerId, $attributeId = null, $optionValue = null)
    {
        $this->addProductForCustomer($productId, $this->resolveCustomerId(), $attributeId, $optionValue);
    }

    /**
     * Add a product to a specific customer's wishlist.
     *
     * Internal, trusted entry point: the customer id is supplied by the caller and is NOT
     * derived from the request token. Do NOT expose this method through the Web API — it is
     * meant for server-side callers (e.g. CLI importers) that operate on behalf of any customer.
     *
     * @param int $productId
     * @param int $customerId
     * @param mixed $attributeId
     * @param mixed $optionValue
     * @return void
     * @throws AlreadyExistsException
     * @throws LocalizedException
     */
    public function addProductForCustomer(int $productId, int $customerId, $attributeId = null, $optionValue = null)
    {
        $wishlist = $this->wishlistFactory->create()->loadByCustomerId($customerId, true);
        $buyRequest = null;
        if ($attributeId !== null && $optionValue !== null) {
            $buyRequest = $this->objectFactory->create()->setData('super_attribute', [$attributeId => $optionValue]);
        }
        $wishlist->addNewItem($productId, $buyRequest);
        $this->wishlistResource->save($wishlist);
    }


    /**
     * @param int $productId
     * @param int $customerId
     * @param int $qty
     * @return void
     * @throws AlreadyExistsException
     * @throws LocalizedException
     */
    public function updateProductQtyToWishlist(int $productId, int $customerId, int $qty)
    {
        $customerId = $this->resolveCustomerId();
        $wishlist = $this->wishlistFactory->create()->loadByCustomerId($customerId);
        if ($wishlist->getId()) {
            $wishItems = $wishlist->getItemCollection();
            foreach ($wishItems as $item) {
                if ((int)$item->getProductId() === $productId) {
                    $buyRequest = $this->objectFactory->create()->setData('qty', $qty);
                    $wishlist->updateItem($item, $buyRequest);
                    $this->wishlistResource->save($wishlist);
                }
            }
        }
    }

    /**
     * @param int $productId
     * @param int $customerId
     * @return void
     * @throws AlreadyExistsException
     * @throws NoSuchEntityException
     */
    public function deleteProductFromWishlist(int $productId, int $customerId)
    {
        $customerId = $this->resolveCustomerId();
        $wishlist = $this->wishlistFactory->create()->loadByCustomerId($customerId);
        if ($wishlist->getId()) {
            $wishItems = $wishlist->getItemCollection();
            foreach ($wishItems as $item) {
                if ((int)$item->getProductId() === $productId) {
                    $item->delete();
                    $this->wishlistResource->save($wishlist);
                }
            }
        }
    }

    /**
     * @param int $customerId
     * @return void
     * @throws AlreadyExistsException
     * @throws NoSuchEntityException
     */
    public function deleteAllProductFromWishlist(int $customerId)
    {
        $customerId = $this->resolveCustomerId();
        $wishlist = $this->wishlistFactory->create()->loadByCustomerId($customerId);
        if ($wishlist->getId()) {
            $wishItems = $wishlist->getItemCollection();
            foreach ($wishItems as $item) {
                $item->delete();
            }
            $this->wishlistResource->save($wishlist);
        }
    }
}
