<?php

declare(strict_types=1);

namespace App\Framework\View\Dom\Query;

use App\Framework\View\Dom\ElementNode;
use App\Framework\View\Dom\Node;

final class QuerySelector
{
    /**
     * Find first element matching selector
     */
    public function querySelector(Node $root, string $selector): ?ElementNode
    {
        $results = $this->querySelectorAll($root, $selector);
        return $results[0] ?? null;
    }

    /**
     * Find all elements matching selector
     *
     * @return array<ElementNode>
     */
    public function querySelectorAll(Node $root, string $selector): array
    {
        $results = [];
        $this->traverse($root, $selector, $results);
        return $results;
    }

    /**
     * @param array<ElementNode> $results
     */
    private function traverse(Node $node, string $selector, array &$results): void
    {
        if ($node instanceof ElementNode) {
            if ($this->matches($node, $selector)) {
                $results[] = $node;
            }
        }

        foreach ($node->getChildren() as $child) {
            $this->traverse($child, $selector, $results);
        }
    }

    private function matches(ElementNode $element, string $selector): bool
    {
        // Simple selector implementation
        // Supports: tagname, .class, #id, [attr], [attr=value]

        // Tag name selector
        if (!str_contains($selector, '.')
            && !str_contains($selector, '#')
            && !str_contains($selector, '[')) {
            return strtolower($element->getTagName()) === strtolower($selector);
        }

        // Class selector
        if (str_starts_with($selector, '.')) {
            $className = substr($selector, 1);
            $classes = explode(' ', $element->getAttribute('class') ?? '');
            return in_array($className, $classes, true);
        }

        // ID selector
        if (str_starts_with($selector, '#')) {
            $id = substr($selector, 1);
            return $element->getAttribute('id') === $id;
        }

        // Attribute selector
        if (preg_match('/\[([a-z-]+)(?:=(["\'])?(.*?)\2)?\]/i', $selector, $matches)) {
            $attrName = $matches[1];

            if (!isset($matches[3])) {
                // [attr] - just check existence
                return $element->hasAttribute($attrName);
            }

            // [attr=value]
            $attrValue = $matches[3];
            return $element->getAttribute($attrName) === $attrValue;
        }

        return false;
    }
}
