<?php
namespace PrimeLink\Modules\Imports\Parsers;

use XMLReader;

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

/**
 * Lightweight XML utilities using XMLReader for streaming operations.
 */
final class XmlHelper {

    /**
     * Scan XML and return a list of paths with counts (potential roots).
     *
     * @param string $file
     * @param array  $opts {limit:int}
     * @return array
     */
    public static function scan_roots( $file, $opts = array() ) {
        $limit = isset( $opts['limit'] ) ? absint( $opts['limit'] ) : 200;

        $reader = new XMLReader();
        if ( ! $reader->open( $file ) ) {
            return array();
        }

        $stack  = array();
        $counts = array();
        $seen   = 0;

        while ( $reader->read() ) {
            if ( $reader->nodeType === XMLReader::ELEMENT ) {
                $stack[ $reader->depth ] = $reader->name;
                $path = implode( '/', array_slice( $stack, 0, $reader->depth + 1 ) );
                $counts[ $path ] = isset( $counts[ $path ] ) ? $counts[ $path ] + 1 : 1;
                $seen++;
                if ( $limit > 0 && $seen >= $limit ) {
                    break;
                }
            }
        }

        $reader->close();

        arsort( $counts );
        $out = array();
        foreach ( $counts as $path => $count ) {
            $out[] = array(
                'path'  => '/' . $path,
                'count' => $count,
            );
        }
        return $out;
    }

    /**
     * Scan tags directly under a given root path.
     *
     * @param string $file
     * @param string $rootPath
     * @param array  $opts {limit:int}
     * @return array
     */
    public static function scan_tags_under_root( $file, $rootPath = '', $opts = array() ) {
        $limit    = isset( $opts['limit'] ) ? absint( $opts['limit'] ) : 300;
        $rootPath = trim( $rootPath, '/' );
        if ( '' === $rootPath ) {
            return array();
        }

        $segments    = explode( '/', $rootPath );
        $targetDepth = count( $segments );
        $targetName  = end( $segments );

        $reader = new XMLReader();
        if ( ! $reader->open( $file ) ) {
            return array();
        }

        $counts = array();
        $seen   = 0;

        while ( $reader->read() ) {
            if ( $reader->nodeType === XMLReader::ELEMENT && $reader->depth === $targetDepth - 1 && $reader->name === $targetName ) {
                $nodeXml = $reader->readOuterXML();
                if ( $nodeXml ) {
                    $node = simplexml_load_string( $nodeXml );
                    if ( $node ) {
                        foreach ( $node->children() as $child ) {
                            $name             = $child->getName();
                            $counts[ $name ]  = isset( $counts[ $name ] ) ? $counts[ $name ] + 1 : 1;
                            // attributes of child
                            foreach ( $child->attributes() as $attrName => $attrVal ) {
                                $key = '@' . $attrName;
                                $counts[ $key ] = isset( $counts[ $key ] ) ? $counts[ $key ] + 1 : 1;
                            }
                            $seen++;
                            if ( $limit > 0 && $seen >= $limit ) {
                                break 2;
                            }
                        }
                        // attributes on the node itself
                        foreach ( $node->attributes() as $attrName => $attrVal ) {
                            $key = '@' . $attrName;
                            $counts[ $key ] = isset( $counts[ $key ] ) ? $counts[ $key ] + 1 : 1;
                        }
                    }
                }
            }
        }

        $reader->close();
        arsort( $counts );
        $out = array();
        foreach ( $counts as $tag => $count ) {
            $out[] = array(
                'tag'   => $tag,
                'count' => $count,
            );
        }
        return $out;
    }
}
