<?php
/**
 * Bricks component nesting depth (max 10, same as Bricks).
 *
 * @package LolaCoreForBricks
 */

declare(strict_types=1);

namespace LolaCoreForBricks\Support;

use LolaCoreForBricks\Elements\ElementTree;
use LolaCoreForBricks\Index\ElementWalker;

/**
 * Measures instance nesting so writes stop at the Bricks recursion limit.
 */
final class ComponentNesting
{
    public const MAX_DEPTH = ElementWalker::MAX_COMPONENT_DEPTH;

    /**
     * @param array<string, mixed> $component
     * @param array<string, array<string, mixed>> $catalog
     */
    public static function internalDepth(array $component, array $catalog, int $depth = 0): int
    {
        if ($depth >= self::MAX_DEPTH) {
            return $depth;
        }

        $max      = $depth;
        $elements = is_array($component['elements'] ?? null) ? $component['elements'] : [];

        foreach ($elements as $element) {
            if (!is_array($element)) {
                continue;
            }

            $cid = isset($element['cid']) ? (string) $element['cid'] : '';
            if ($cid === '' || !isset($catalog[$cid]) || !is_array($catalog[$cid])) {
                continue;
            }

            $max = max($max, self::internalDepth($catalog[$cid], $catalog, $depth + 1));
        }

        return $max;
    }

    public static function ancestorDepth(ElementTree $tree, string $elementId): int
    {
        $depth = 0;
        $id    = $elementId;
        $seen  = [];

        while ($id !== '') {
            if (isset($seen[$id])) {
                break;
            }
            $seen[$id] = true;

            $element = $tree->findById($id);
            if ($element === null) {
                break;
            }

            if (isset($element['cid']) && (string) $element['cid'] !== '') {
                ++$depth;
            }

            $parent = $element['parent'] ?? ElementTree::ROOT_PARENT;
            $id     = ($parent === ElementTree::ROOT_PARENT || $parent === '0' || $parent === '' || $parent === null)
                ? ''
                : (string) $parent;
        }

        return $depth;
    }

    /**
     * @return array{depth: int, at_limit: bool, over_limit: bool}
     */
    public static function evaluate(int $depth): array
    {
        return [
            'depth'      => $depth,
            'at_limit'   => $depth === self::MAX_DEPTH,
            'over_limit' => $depth > self::MAX_DEPTH,
        ];
    }
}
