<?php
/**
 * Copyright © Simplyin. All rights reserved.
 */
declare(strict_types=1);

namespace Simplyin\Payment\Service;

use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Store\Model\ScopeInterface;
use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable as ConfigurableType;
use Magento\GroupedProduct\Model\ResourceModel\Product\Link as GroupedType;
use Magento\Bundle\Model\ResourceModel\Selection as BundleSelection;
use Magento\Store\Model\StoreManagerInterface;
use Psr\Log\LoggerInterface;

/**
 * Resolves the frontend-visible product URL for an order/quote line product.
 *
 * For products that are not individually visible (configurable/grouped/bundle
 * children) it resolves the visible parent, then builds the URL from the store
 * base URL + url_key so no admin URL leaks in a cron context. Extracted from
 * OrderPayloadBuilder so that class keeps a single responsibility.
 */
class VisibleProductUrlResolver
{
    /**
     * @var ScopeConfigInterface
     */
    private $scopeConfig;

    /**
     * @var ProductRepositoryInterface
     */
    private $productRepository;

    /**
     * @var ConfigurableType
     */
    private $configurableType;

    /**
     * @var GroupedType
     */
    private $groupedType;

    /**
     * @var BundleSelection
     */
    private $bundleSelection;

    /**
     * @var StoreManagerInterface
     */
    private $storeManager;

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

    /**
     * @param ScopeConfigInterface $scopeConfig
     * @param ProductRepositoryInterface $productRepository
     * @param ConfigurableType $configurableType
     * @param GroupedType $groupedType
     * @param BundleSelection $bundleSelection
     * @param StoreManagerInterface $storeManager
     * @param LoggerInterface $logger
     */
    public function __construct(
        ScopeConfigInterface $scopeConfig,
        ProductRepositoryInterface $productRepository,
        ConfigurableType $configurableType,
        GroupedType $groupedType,
        BundleSelection $bundleSelection,
        StoreManagerInterface $storeManager,
        LoggerInterface $logger
    ) {
        $this->scopeConfig = $scopeConfig;
        $this->productRepository = $productRepository;
        $this->configurableType = $configurableType;
        $this->groupedType = $groupedType;
        $this->bundleSelection = $bundleSelection;
        $this->storeManager = $storeManager;
        $this->logger = $logger;
    }

    /**
     * Get the frontend-visible product URL, resolving the parent for child products.
     *
     * @param \Magento\Catalog\Api\Data\ProductInterface $product
     * @param int|null $storeId
     * @return string
     */
    public function resolve($product, $storeId = null): string
    {
        $targetProduct = $product;

        // If product is not visible individually, find its parent
        $visibility = (int) $product->getVisibility();
        if ($visibility === \Magento\Catalog\Model\Product\Visibility::VISIBILITY_NOT_VISIBLE) {
            $parentIds = $this->resolveParentIds($product->getId());
            if (!empty($parentIds)) {
                // Load the parent in the order's store view so url_key resolves correctly on multi-store
                $targetProduct = $this->productRepository->getById($parentIds[0], false, $storeId);
            }
        }

        // Build frontend URL from store base URL + url_key (avoids admin URL in cron context)
        $urlKey = $targetProduct->getUrlKey();
        if ($urlKey) {
            try {
                $store = $this->storeManager->getStore($storeId);
                $baseUrl = $store->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_LINK);
                $suffix = $this->scopeConfig->getValue(
                    'catalog/seo/product_url_suffix',
                    ScopeInterface::SCOPE_STORE,
                    $storeId
                );
                return $baseUrl . $urlKey . ($suffix ?: '');
            } catch (\Exception $e) {
                $this->logger->debug('Could not build product URL from store: ' . $e->getMessage());
            }
        }

        return '';
    }

    /**
     * Resolve parent product IDs for a child product.
     *
     * Checks configurable, grouped, and bundle parent relationships in order.
     *
     * @param int $productId
     * @return array
     */
    private function resolveParentIds($productId): array
    {
        // Check configurable parent
        $parentIds = $this->configurableType->getParentIdsByChild($productId);
        if (empty($parentIds)) {
            // Check grouped parent
            $parentIds = $this->groupedType->getParentIdsByChild($productId);
        }
        if (empty($parentIds)) {
            // Check bundle parent
            $parentIds = $this->bundleSelection->getParentIdsByChild($productId);
        }

        return $parentIds;
    }
}
