<?php
/**
 * Health check collector.
 *
 * @package MonitorCat\Modules\Diagnostics\Collector
 */

declare(strict_types=1);

namespace MonitorCat\Modules\Diagnostics\Collector;

defined( 'ABSPATH' ) || exit;

/**
 * Collects health-related information including cron status, REST API, security, and caching.
 */
final class HealthCollector {

	/**
	 * Collect health check data.
	 *
	 * @return array{label: string, icon: string, items: array<int, array{label: string, value: string, status?: string}>}
	 */
	public function collect(): array {
		$items = array(
			$this->get_cron_status(),
			$this->get_next_cron_event(),
			$this->get_rest_api_status(),
			$this->get_https_status(),
			$this->get_permalink_status(),
		);

		$htaccess_item = $this->get_htaccess_status();
		if ( null !== $htaccess_item ) {
			$items[] = $htaccess_item;
		}

		$items[] = $this->get_wp_config_permissions();
		$items[] = $this->get_wp_content_writable();
		$items[] = $this->get_object_cache_status();

		return array(
			'label' => __( 'Health', 'monitor-cat' ),
			'icon'  => 'fa-heart-pulse',
			'items' => $items,
		);
	}

	/**
	 * Get the WordPress cron status.
	 *
	 * @return array{label: string, value: string, status: string}
	 */
	private function get_cron_status(): array {
		if ( defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON ) {
			return array(
				'label'  => __( 'WordPress Cron', 'monitor-cat' ),
				'value'  => __( 'Disabled via DISABLE_WP_CRON', 'monitor-cat' ),
				'status' => 'warning',
			);
		}

		return array(
			'label'  => __( 'WordPress Cron', 'monitor-cat' ),
			'value'  => __( 'Enabled', 'monitor-cat' ),
			'status' => 'good',
		);
	}

	/**
	 * Get the next scheduled cron event.
	 *
	 * @return array{label: string, value: string}
	 */
	private function get_next_cron_event(): array {
		$cron_array = _get_cron_array();

		if ( empty( $cron_array ) ) {
			return array(
				'label' => __( 'Next Cron Event', 'monitor-cat' ),
				'value' => __( 'No events scheduled', 'monitor-cat' ),
			);
		}

		$next_timestamp = min( array_keys( $cron_array ) );

		return array(
			'label' => __( 'Next Cron Event', 'monitor-cat' ),
			'value' => sprintf(
				/* translators: %s: human-readable time difference */
				__( 'In %s', 'monitor-cat' ),
				human_time_diff( time(), $next_timestamp )
			),
		);
	}

	/**
	 * Get the REST API status by performing a loopback request.
	 *
	 * @return array{label: string, value: string, status: string}
	 */
	private function get_rest_api_status(): array {
		$rest_url = rest_url( 'wp/v2/types' );
		$response = wp_remote_get(
			$rest_url,
			array(
				'timeout'   => 5,
				'sslverify' => false,
			)
		);

		if ( is_wp_error( $response ) ) {
			return array(
				'label'  => __( 'REST API', 'monitor-cat' ),
				'value'  => $response->get_error_message(),
				'status' => 'warning',
			);
		}

		$status_code = wp_remote_retrieve_response_code( $response );

		if ( 200 === $status_code ) {
			return array(
				'label'  => __( 'REST API', 'monitor-cat' ),
				'value'  => __( 'Available', 'monitor-cat' ),
				'status' => 'good',
			);
		}

		return array(
			'label'  => __( 'REST API', 'monitor-cat' ),
			'value'  => sprintf(
				/* translators: %d: HTTP status code */
				__( 'Responded with status %d', 'monitor-cat' ),
				$status_code
			),
			'status' => 'warning',
		);
	}

	/**
	 * Get the HTTPS status.
	 *
	 * @return array{label: string, value: string, status: string}
	 */
	private function get_https_status(): array {
		return array(
			'label'  => __( 'HTTPS', 'monitor-cat' ),
			'value'  => is_ssl()
				? __( 'Yes', 'monitor-cat' )
				: __( 'No', 'monitor-cat' ),
			'status' => is_ssl() ? 'good' : 'warning',
		);
	}

	/**
	 * Get the permalink structure status.
	 *
	 * @return array{label: string, value: string, status: string}
	 */
	private function get_permalink_status(): array {
		$permalink_structure = get_option( 'permalink_structure' );

		if ( ! empty( $permalink_structure ) ) {
			return array(
				'label'  => __( 'Permalink Structure', 'monitor-cat' ),
				'value'  => $permalink_structure,
				'status' => 'good',
			);
		}

		return array(
			'label'  => __( 'Permalink Structure', 'monitor-cat' ),
			'value'  => __( 'Plain', 'monitor-cat' ),
			'status' => 'warning',
		);
	}

	/**
	 * Get the .htaccess writable status (Apache only).
	 *
	 * @return array{label: string, value: string, status: string}|null Null if not on Apache.
	 */
	private function get_htaccess_status(): ?array {
		if ( ! isset( $_SERVER['SERVER_SOFTWARE'] ) ||
			false === stripos( sanitize_text_field( wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) ), 'apache' )
		) {
			return null;
		}

		$htaccess_path = ABSPATH . '.htaccess';
		$is_writable   = file_exists( $htaccess_path ) && wp_is_writable( $htaccess_path );

		return array(
			'label'  => __( '.htaccess Writable', 'monitor-cat' ),
			'value'  => $is_writable
				? __( 'Yes', 'monitor-cat' )
				: __( 'No', 'monitor-cat' ),
			'status' => $is_writable ? 'good' : 'warning',
		);
	}

	/**
	 * Get wp-config.php file permissions.
	 *
	 * @return array{label: string, value: string}
	 */
	private function get_wp_config_permissions(): array {
		$config_path = ABSPATH . 'wp-config.php';

		if ( ! file_exists( $config_path ) ) {
			$config_path = dirname( ABSPATH ) . '/wp-config.php';
		}

		if ( ! file_exists( $config_path ) ) {
			return array(
				'label' => __( 'wp-config.php Permissions', 'monitor-cat' ),
				'value' => __( 'File not found', 'monitor-cat' ),
			);
		}

		$perms = fileperms( $config_path );

		if ( false === $perms ) {
			return array(
				'label' => __( 'wp-config.php Permissions', 'monitor-cat' ),
				'value' => __( 'Unable to determine', 'monitor-cat' ),
			);
		}

		return array(
			'label' => __( 'wp-config.php Permissions', 'monitor-cat' ),
			'value' => substr( sprintf( '%o', $perms ), -4 ),
		);
	}

	/**
	 * Get the wp-content directory writable status.
	 *
	 * @return array{label: string, value: string, status: string}
	 */
	private function get_wp_content_writable(): array {
		$is_writable = wp_is_writable( WP_CONTENT_DIR );

		return array(
			'label'  => __( 'wp-content Writable', 'monitor-cat' ),
			'value'  => $is_writable
				? __( 'Yes', 'monitor-cat' )
				: __( 'No', 'monitor-cat' ),
			'status' => $is_writable ? 'good' : 'warning',
		);
	}

	/**
	 * Get the object cache status.
	 *
	 * @return array{label: string, value: string, status?: string}
	 */
	private function get_object_cache_status(): array {
		$using_ext_cache = wp_using_ext_object_cache();

		if ( $using_ext_cache ) {
			$cache_type = __( 'External object cache enabled', 'monitor-cat' );

			if ( class_exists( 'Redis' ) || class_exists( 'Predis\Client' ) ) {
				$cache_type = __( 'Redis', 'monitor-cat' );
			} elseif ( class_exists( 'Memcached' ) ) {
				$cache_type = __( 'Memcached', 'monitor-cat' );
			} elseif ( class_exists( 'Memcache' ) ) {
				$cache_type = __( 'Memcache', 'monitor-cat' );
			}

			return array(
				'label'  => __( 'Object Cache', 'monitor-cat' ),
				'value'  => $cache_type,
				'status' => 'good',
			);
		}

		return array(
			'label' => __( 'Object Cache', 'monitor-cat' ),
			'value' => __( 'Not using external object cache', 'monitor-cat' ),
		);
	}
}
