<?php
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class ASA_Inventory_Scan {

	private $payload_cache = array();

	public function run( array $payload = array(), array $args = array() ) {
		if ( empty( $payload ) ) {
			$payload = $this->build_payload( $args );
		}
		$inventory = ! empty( $payload['inventory'] ) && is_array( $payload['inventory'] ) ? $payload['inventory'] : array();
		$plugins   = ! empty( $inventory['plugins'] ) && is_array( $inventory['plugins'] ) ? $inventory['plugins'] : array( 'active' => array(), 'inactive' => array() );
		$themes    = ! empty( $inventory['themes'] ) && is_array( $inventory['themes'] ) ? $inventory['themes'] : array( 'active' => array(), 'inactive' => array() );
		$core      = ! empty( $inventory['wordpress_core'] ) && is_array( $inventory['wordpress_core'] ) ? $inventory['wordpress_core'] : array();
		$runtime   = ! empty( $inventory['runtime'] ) && is_array( $inventory['runtime'] ) ? $inventory['runtime'] : array();
		$roles     = ! empty( $inventory['roles'] ) && is_array( $inventory['roles'] ) ? $inventory['roles'] : array();
		$db_posture = ! empty( $inventory['db_posture'] ) && is_array( $inventory['db_posture'] ) ? $inventory['db_posture'] : array();
		$db_privileges = ! empty( $inventory['db_privileges'] ) && is_array( $inventory['db_privileges'] ) ? $inventory['db_privileges'] : array();
		$rest      = ! empty( $inventory['rest_routes'] ) && is_array( $inventory['rest_routes'] ) ? $inventory['rest_routes'] : array();
		$ajax      = ! empty( $inventory['admin_ajax_actions'] ) && is_array( $inventory['admin_ajax_actions'] ) ? $inventory['admin_ajax_actions'] : array();
		$composer  = ! empty( $inventory['composer_packages'] ) && is_array( $inventory['composer_packages'] ) ? $inventory['composer_packages'] : array();
		$python    = ! empty( $inventory['python_packages'] ) && is_array( $inventory['python_packages'] ) ? $inventory['python_packages'] : array();
		$js        = ! empty( $inventory['js_packages'] ) && is_array( $inventory['js_packages'] ) ? $inventory['js_packages'] : array();
		$npm       = ! empty( $inventory['npm_packages'] ) && is_array( $inventory['npm_packages'] ) ? $inventory['npm_packages'] : array();
		$yarn      = ! empty( $inventory['yarn_packages'] ) && is_array( $inventory['yarn_packages'] ) ? $inventory['yarn_packages'] : array();
		$pnpm      = ! empty( $inventory['pnpm_packages'] ) && is_array( $inventory['pnpm_packages'] ) ? $inventory['pnpm_packages'] : array();
		$audits    = ! empty( $inventory['dependency_audits'] ) && is_array( $inventory['dependency_audits'] ) ? $inventory['dependency_audits'] : array();

		$results = array();
		$results[] = array(
			'severity' => 'info',
			'category' => 'inventory',
			'title'    => 'Plugin inventory',
			'details'  => sprintf( 'Detected %d active plugins, %d inactive plugins, and %d must-use plugins.', count( $plugins['active'] ), count( $plugins['inactive'] ), ! empty( $inventory['mu_plugins'] ) ? count( $inventory['mu_plugins'] ) : 0 ),
		);
		$results[] = array(
			'severity' => 'info',
			'category' => 'inventory',
			'title'    => 'Theme inventory',
			'details'  => sprintf( 'Detected %d active themes and %d inactive themes.', count( $themes['active'] ), count( $themes['inactive'] ) ),
		);
		$results[] = array(
			'severity' => ! empty( $core['update_available'] ) ? 'medium' : 'passed',
			'category' => 'updates',
			'title'    => 'Core update backlog',
			'details'  => ! empty( $core['update_available'] ) ? 'Core updates are available.' : 'No core updates detected.',
		);
		$results[] = array(
			'severity' => count( $rest ) > 0 ? 'info' : 'medium',
			'category' => 'inventory',
			'title'    => 'REST route inventory',
			'details'  => count( $rest ) > 0 ? sprintf( 'Captured %d REST routes from the local WordPress application, including %d routes that appear public.', count( $rest ), count( array_filter( $rest, static function( $route ) { return ! empty( $route['public'] ); } ) ) ) : 'No REST routes were captured locally.',
		);
		$results[] = array(
			'severity' => count( $ajax ) > 0 ? 'info' : 'passed',
			'category' => 'inventory',
			'title'    => 'admin-ajax action inventory',
			'details'  => count( $ajax ) > 0 ? sprintf( 'Captured %d registered admin-ajax actions, including %d public wp_ajax_nopriv hooks.', count( $ajax ), count( array_filter( $ajax, static function( $action ) { return ! empty( $action['public'] ); } ) ) ) : 'No registered admin-ajax actions were captured.',
		);
		$results[] = array(
			'severity' => ! empty( $runtime['loopback_status'] ) && 'ok' === $runtime['loopback_status'] ? 'passed' : 'medium',
			'category' => 'runtime',
			'title'    => 'Loopback and HTTP runtime posture',
			'details'  => sprintf( 'Loopback status: %s. HTTP API: %s. cURL: %s.', ! empty( $runtime['loopback_status'] ) ? $runtime['loopback_status'] : 'unknown', ! empty( $runtime['http_api'] ) ? 'enabled' : 'disabled', ! empty( $runtime['curl_enabled'] ) ? 'enabled' : 'disabled' ),
		);

		$results[] = array(
			'severity' => ! empty( $roles ) ? 'info' : 'passed',
			'category' => 'inventory',
			'title'    => 'Role and capability inventory',
			'details'  => sprintf( 'Captured %d WordPress roles, with %d roles carrying privileged administrative capabilities.', count( $roles ), count( array_filter( $roles, static function( $role ) { return ! empty( $role['privileged'] ); } ) ) ),
		);
		$results[] = array(
			'severity' => ( ! empty( $db_privileges['has_all_privileges'] ) || ! empty( $db_privileges['has_file_priv'] ) || ! empty( $db_privileges['has_super_priv'] ) ) ? 'medium' : 'passed',
			'category' => 'runtime',
			'title'    => 'Database privilege and config posture',
			'details'  => sprintf(
				'Database posture captured. sql_mode: %1$s. Grants visible: %2$s. Elevated FILE/SUPER/ALL privileges: %3$s.',
				! empty( $db_posture['sql_mode'] ) ? $db_posture['sql_mode'] : 'unknown',
				! empty( $db_privileges['status'] ) ? $db_privileges['status'] : 'unavailable',
				( ! empty( $db_privileges['has_all_privileges'] ) || ! empty( $db_privileges['has_file_priv'] ) || ! empty( $db_privileges['has_super_priv'] ) ) ? 'yes' : 'no'
			),
		);
		$results[] = array(
			'severity' => ( count( $composer ) + count( $python ) + count( $js ) ) > 0 ? 'info' : 'passed',
			'category' => 'inventory',
			'title'    => 'Dependency manifest inventory',
			'details'  => sprintf( 'Captured %d Composer packages, %d Python packages, and %d JavaScript packages from local manifests (%d npm, %d Yarn, %d pnpm).', count( $composer ), count( $python ), count( $js ), count( $npm ), count( $yarn ), count( $pnpm ) ),
		);

		if ( ! empty( $audits['composer'] ) && 'success' === $audits['composer']['status'] ) {
			$results[] = array(
				'severity' => 'medium',
				'category' => 'dependencies',
				'title'    => 'Composer dependency advisories',
				'details'  => sprintf( 'composer audit returned %d advisory records from local dependency manifests.', count( $audits['composer']['records'] ) ),
			);
		}
		if ( ! empty( $audits['pip'] ) && 'success' === $audits['pip']['status'] ) {
			$results[] = array(
				'severity' => 'medium',
				'category' => 'dependencies',
				'title'    => 'Python dependency advisories',
				'details'  => sprintf( 'pip-audit returned %d advisory records from local Python packages.', count( $audits['pip']['records'] ) ),
			);
		}
		if ( ! empty( $audits['npm'] ) && 'success' === $audits['npm']['status'] ) {
			$results[] = array(
				'severity' => 'medium',
				'category' => 'dependencies',
				'title'    => 'npm dependency advisories',
				'details'  => sprintf( 'npm audit returned %d advisory records from local package-lock manifests.', count( $audits['npm']['records'] ) ),
			);
		}
		if ( ! empty( $audits['yarn'] ) && 'success' === $audits['yarn']['status'] ) {
			$results[] = array(
				'severity' => 'medium',
				'category' => 'dependencies',
				'title'    => 'Yarn dependency advisories',
				'details'  => sprintf( 'yarn audit returned %d advisory records from local yarn.lock manifests.', count( $audits['yarn']['records'] ) ),
			);
		}
		if ( ! empty( $audits['pnpm'] ) && 'success' === $audits['pnpm']['status'] ) {
			$results[] = array(
				'severity' => 'medium',
				'category' => 'dependencies',
				'title'    => 'pnpm dependency advisories',
				'details'  => sprintf( 'pnpm audit returned %d advisory records from local pnpm-lock manifests.', count( $audits['pnpm']['records'] ) ),
			);
		}

		return $results;
	}

	public function build_payload( array $args = array() ) {
		$normalized_args = wp_parse_args(
			$args,
			array(
				'include_dependency_audits' => true,
			)
		);
		$cache_key = md5( wp_json_encode( $normalized_args ) );
		if ( isset( $this->payload_cache[ $cache_key ] ) ) {
			return $this->payload_cache[ $cache_key ];
		}

		$this->payload_cache[ $cache_key ] = ASA_Local_Inventory::generate( $normalized_args );
		return $this->payload_cache[ $cache_key ];
	}
}
