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

namespace WriteTextAI\WriteTextAI\Model\OptionSource\Filter;

use Magento\Catalog\Model\ResourceModel\Category\CollectionFactory;
use Magento\Framework\Data\OptionSourceInterface;

class Categories implements OptionSourceInterface
{
    public const NO_CATEGORY_VALUE = '__no_category__';

    /**
     * @var CollectionFactory
     */
    protected $categoryCollectionFactory;

    /**
     * @param CollectionFactory $categoryCollectionFactory
     */
    public function __construct(
        CollectionFactory $categoryCollectionFactory
    ) {
        $this->categoryCollectionFactory = $categoryCollectionFactory;
    }

    /**
     * Get options array
     *
     * @return array
     */
    public function toOptionArray()
    {
        $collection = $this->categoryCollectionFactory->create();
        $collection->setStoreId(0);
        $collection->addAttributeToSelect('name');
        $collection->addAttributeToSelect('parent_id');
        $collection->addFieldToFilter('level', ['gteq' => 0]);
        $collection->addFieldToFilter('entity_id', ['neq' => 1]);
        $collection->setOrder('entity_id', 'ASC');

        $nodes = [];
        foreach ($collection as $category) {
            $categoryId = (int)$category->getId();
            $nodes[$categoryId] = [
                'id' => $categoryId,
                'parent_id' => (int)$category->getParentId(),
                'label' => (string)$category->getName(),
                'children' => []
            ];
        }

        $roots = [];
        foreach ($nodes as $categoryId => $node) {
            $parentId = $node['parent_id'];
            if (isset($nodes[$parentId])) {
                $nodes[$parentId]['children'][] = $categoryId;
            } else {
                $roots[] = $categoryId;
            }
        }

        $buildOptions = function (array $ids) use (&$buildOptions, $nodes): array {
            $options = [];
            foreach ($ids as $id) {
                if (!isset($nodes[$id])) {
                    continue;
                }

                $node = $nodes[$id];
                $option = [
                    'label' => $node['label'],
                    'value' => (int)$node['id']
                ];

                if (!empty($node['children'])) {
                    $option['optgroup'] = $buildOptions($node['children']);
                }

                $options[] = $option;
            }

            return $options;
        };

        return array_merge($buildOptions($roots), [
            [
                'label' => (string)__('No Category'),
                'value' => self::NO_CATEGORY_VALUE
            ]
        ]);
    }
}
