<?php
/**
 * Structure Viewer — Dashboard
 *
 * Dashboard statistics and async top-plugins computation.
 */

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

final class SV_Dashboard {

    const TRANSIENT_FILE_COUNT  = 'structureviewer_file_count';
    const TRANSIENT_TOP_PLUGINS = 'structureviewer_top_plugins';
    const CACHE_TTL             = 21600; // 6 hours
    // Bump this string whenever the file-count scope changes (forces cache rebuild)
    const FILE_COUNT_VER        = '2.2.1-themes';

    /**
     * Return all data needed for the dashboard tab.
     * Top-plugins list is intentionally left empty on cold cache;
     * the JS will fire an AJAX call to fill it asynchronously.
     */
    public static function get_stats() {
        $plugin_dirs = glob( WP_PLUGIN_DIR . '/*', GLOB_ONLYDIR ) ?: [];
        $theme_dirs  = glob( get_theme_root() . '/*', GLOB_ONLYDIR ) ?: [];

        // Active vs inactive plugin count
        $active_slugs   = array_map(
            fn( $p ) => explode( '/', $p )[0],
            (array) get_option( 'active_plugins', [] )
        );
        $active_count   = count( array_filter( $active_slugs ) );
        $inactive_count = max( 0, count( $plugin_dirs ) - $active_count );

        // Total file count (cached; samples first 10 plugins + all themes for speed)
        // Transient key includes FILE_COUNT_VER so bumping the version forces rebuild.
        $file_count_key = self::TRANSIENT_FILE_COUNT . '_' . self::FILE_COUNT_VER;
        $file_count     = get_transient( $file_count_key );
        if ( $file_count === false ) {
            $file_count  = 0;
            $sample_dirs = array_merge(
                array_slice( $plugin_dirs, 0, 10 ),
                $theme_dirs
            );
            foreach ( $sample_dirs as $dir ) {
                try {
                    $it = new RecursiveIteratorIterator(
                        new RecursiveDirectoryIterator( $dir, RecursiveDirectoryIterator::SKIP_DOTS )
                    );
                    foreach ( $it as $f ) {
                        if ( $f->isFile() ) {
                            $file_count++;
                        }
                    }
                } catch ( Exception $e ) { // phpcs:ignore
                    // skip unreadable dirs
                }
            }
            set_transient( $file_count_key, $file_count, self::CACHE_TTL );
        }

        // Top plugins — return empty on cold cache; AJAX fills it
        $top_plugins = get_transient( self::TRANSIENT_TOP_PLUGINS ) ?: [];

        $active_theme = wp_get_theme();

        return [
            'plugins'     => count( $plugin_dirs ),
            'active'      => $active_count,
            'inactive'    => $inactive_count,
            'themes'      => count( $theme_dirs ),
            'files'       => $file_count > 0 ? number_format( $file_count ) : '—',
            'top_plugins' => $top_plugins,
            'env'         => [
                'wp_version'   => get_bloginfo( 'version' ),
                'php_version'  => PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION . '.' . PHP_RELEASE_VERSION,
                'active_theme' => $active_theme->get( 'Name' ) ?: '—',
                'site_url'     => wp_parse_url( get_site_url(), PHP_URL_HOST ),
            ],
        ];
    }

    /** AJAX: compute top 5 plugins by file count (background call). */
    public static function ajax_get_top_plugins() {
        check_ajax_referer( STRUCTUREVIEWER_NONCE, 'nonce' );

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

        $cached = get_transient( self::TRANSIENT_TOP_PLUGINS );
        if ( $cached !== false ) {
            wp_send_json_success( $cached );
            return;
        }

        $excl    = SV_Filters::exclusion_patterns();
        $dirs    = glob( WP_PLUGIN_DIR . '/*', GLOB_ONLYDIR ) ?: [];
        $results = [];

        foreach ( $dirs as $dir ) {
            $folder = basename( $dir );
            $count  = 0;
            $size   = 0;
            try {
                $it = new RecursiveIteratorIterator(
                    new RecursiveDirectoryIterator( $dir, RecursiveDirectoryIterator::SKIP_DOTS )
                );
                foreach ( $it as $f ) {
                    if ( ! $f->isFile() ) {
                        continue;
                    }
                    $skip = false;
                    foreach ( $excl as $p ) {
                        if ( fnmatch( $p, $f->getFilename() ) ) {
                            $skip = true;
                            break;
                        }
                    }
                    if ( $skip ) {
                        continue;
                    }
                    $count++;
                    $size += $f->getSize();
                }
            } catch ( Exception $e ) { // phpcs:ignore
                // skip
            }

            $main   = SV_ItemData::find_main_plugin_file( $dir );
            $name   = $main
                ? ( get_plugin_data( $main, false, false )['Name'] ?? $folder )
                : $folder;

            $results[ $folder ] = [
                'name'   => $name,
                'files'  => $count,
                'size'   => $size,
                'folder' => $folder,
            ];
        }

        uasort( $results, fn( $a, $b ) => $b['files'] - $a['files'] );
        $top = array_slice( $results, 0, 5, true );

        set_transient( self::TRANSIENT_TOP_PLUGINS, $top, self::CACHE_TTL );
        wp_send_json_success( $top );
    }
}