<?php
/**
 * @author 1902 Software
 * @copyright Copyright © 2023 1902 Software (https://1902software.com/magento/)
 * @package WriteTextAI_WriteTextAI
 */

declare(strict_types=1);

namespace WriteTextAI\WriteTextAI\Controller\Adminhtml\Edit;

use Magento\Backend\App\Action;
use Magento\Backend\App\Action\Context;
use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Catalog\Model\Product\Attribute\Source\Status;
use Magento\ConfigurableProduct\Model\Product\Type\Configurable as ConfigurableType;
use Magento\Framework\Controller\ResultFactory;
use Magento\GroupedProduct\Model\Product\Type\Grouped as GroupedType;
use Magento\Store\Model\StoreManagerInterface;
use WriteTextAI\WriteTextAI\Helper\Product as ProductHelper;

class ChildProducts extends Action
{
    public const ADMIN_RESOURCE = 'WriteTextAI_WriteTextAI::edit';

    /**
     * @var ProductHelper
     */
    private $productHelper;

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

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

    /**
     * @param Context $context
     * @param ProductHelper $productHelper
     * @param ProductRepositoryInterface $productRepository
     * @param StoreManagerInterface $storeManager
     */
    public function __construct(
        Context $context,
        ProductHelper $productHelper,
        ProductRepositoryInterface $productRepository,
        StoreManagerInterface $storeManager
    ) {
        parent::__construct($context);
        $this->productHelper = $productHelper;
        $this->productRepository = $productRepository;
        $this->storeManager = $storeManager;
    }

    /**
     * Get child products
     *
     * @return \Magento\Framework\Controller\ResultInterface
     */
    public function execute()
    {
        $result = $this->resultFactory->create(ResultFactory::TYPE_JSON);

        try {
            $productId = (int) $this->getRequest()->getParam('product_id');
            $storeId = (int) $this->getRequest()->getParam('store_id');

            if (!$productId) {
                return $result->setData([
                    'success' => false,
                    'items' => []
                ]);
            }

            $product = $this->productHelper->getProduct($productId, $storeId);

            $typeId = (string) $product->getTypeId();
            $childIds = [];

            if ($typeId === ConfigurableType::TYPE_CODE) {
                $childIds = $product->getTypeInstance()->getUsedProductIds($product);
            } elseif ($typeId === GroupedType::TYPE_CODE) {
                $childIds = $product->getTypeInstance()->getAssociatedProductIds($product);
            } elseif ($typeId === 'bundle') {
                $childIds = $product->getTypeInstance()->getChildrenIds($product->getId(), false);
                $flattened = [];
                foreach ($childIds as $optionChildren) {
                    foreach ((array) $optionChildren as $childId) {
                        $flattened[] = (int) $childId;
                    }
                }
                $childIds = $flattened;
            }

            $childIds = array_values(array_unique(array_filter($childIds)));

            if (empty($childIds)) {
                return $result->setData([
                    'success' => true,
                    'items' => []
                ]);
            }

            $items = [];
            foreach ($childIds as $childId) {
                try {
                    $child = $this->productRepository->getById((int) $childId, false, $storeId);
                } catch (\Exception $e) {
                    continue;
                }

                if ((int) $child->getStatus() !== Status::STATUS_ENABLED) {
                    continue;
                }

                $items[] = [
                    'id' => (int) $child->getId(),
                    'name' => (string) $child->getName(),
                    'sku' => (string) $child->getSku()
                ];
            }

            usort($items, static function ($a, $b) {
                return strcmp($a['name'], $b['name']);
            });

            return $result->setData([
                'success' => true,
                'items' => $items
            ]);
        } catch (\Exception $e) {
            return $result->setData([
                'success' => false,
                'items' => [],
                'error' => $e->getMessage()
            ]);
        }
    }
}
