<?php
/**
 * Structure Viewer — Search
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit( 'Direct access denied.' );
}

final class SV_Search {

    /** AJAX handler. Uses a dedicated search nonce. */
    public static function ajax_search() {
        check_ajax_referer( 'structureviewer_search_nonce', 'nonce' );

        if ( ! current_user_can( 'manage_options' ) ) {
            wp_send_json_error( [ 'message' => 'Insufficient permissions.' ] );
        }

        $term = isset( $_POST['search_term'] ) ? sanitize_text_field( wp_unslash( $_POST['search_term'] ) ) : '';
        $type = isset( $_POST['type'] )        ? sanitize_text_field( wp_unslash( $_POST['type'] ) )        : 'plugin';
        $item = isset( $_POST['item'] )        ? SV_Sanitizer::item_name( sanitize_text_field( wp_unslash( $_POST['item'] ) ) )    : '';

        if ( empty( $term ) ) {
            wp_send_json_error( [ 'message' => 'Search term is required.' ] );
        }

        wp_send_json_success( self::search_files( $type, $item, $term ) );
    }

    /**
     * Recursively search $type/$item for files matching $term.
     * If $term starts with '.' it is treated as an extension filter.
     * Returns up to 200 results.
     */
    public static function search_files( $type, $item, $term ) {
        // Whitelist $type — any non-matching value previously fell through to
        // themes silently, which could mask caller bugs and give surprising
        // results. Return [] instead.
        if ( ! in_array( $type, [ 'plugin', 'theme' ], true ) ) {
            return [];
        }

        $items_dir = ( $type === 'plugin' ) ? WP_PLUGIN_DIR : get_theme_root();
        $base      = realpath( $items_dir . '/' . $item );

        if ( ! $base || ! is_dir( $base ) ) {
            return [];
        }

        $results  = [];
        $patterns = SV_Filters::exclusion_patterns();
        $is_ext   = ( strpos( $term, '.' ) === 0 );
        $ext_term = $is_ext ? strtolower( ltrim( $term, '.' ) ) : '';

        $it = new RecursiveIteratorIterator(
            new RecursiveDirectoryIterator( $base, RecursiveDirectoryIterator::SKIP_DOTS ),
            RecursiveIteratorIterator::SELF_FIRST
        );

        foreach ( $it as $file ) {
            $filename = $file->getFilename();

            // Skip excluded
            foreach ( $patterns as $pat ) {
                if ( fnmatch( $pat, $filename ) ) {
                    continue 2;
                }
            }

            $matched = $is_ext
                ? ( strtolower( pathinfo( $filename, PATHINFO_EXTENSION ) ) === $ext_term )
                : ( stripos( $filename, $term ) !== false );

            if ( ! $matched ) {
                continue;
            }

            $rel       = str_replace( $base . '/', '', $file->getPathname() );
            $results[] = [
                'name'     => $filename,
                'path'     => $rel,
                'is_dir'   => $file->isDir(),
                'size'     => $file->isFile() ? size_format( $file->getSize(), 2 ) : '',
                'modified' => $file->isFile() ? gmdate( 'Y-m-d H:i:s', $file->getMTime() ) : '',
            ];

            if ( count( $results ) >= 200 ) {
                break;
            }
        }

        return $results;
    }
}