<?php

namespace Waypoint\Agent\Monitor;

class Status_Data {

	public function payload(): array {
		return [
			'plugin_version'     => WAYPOINT_AGENT_VERSION,
			'wp_version'         => get_bloginfo( 'version' ),
			'php_version'        => PHP_VERSION,
			'site_url'           => home_url(),
			'admin_email'        => get_bloginfo( 'admin_email' ),
			'deployed_sha'       => $this->deployed_sha(),
			'composer_lock_hash' => $this->composer_lock_hash(),
			'plugins'            => $this->plugin_list(),
			'themes'             => $this->theme_list(),
			'checked_at'         => gmdate( 'c' ),
		];
	}

	private function deployed_sha(): ?string {
		$candidates = [ ABSPATH, dirname( ABSPATH ), dirname( ABSPATH, 2 ) ];
		foreach ( $candidates as $dir ) {
			$head_path = rtrim( $dir, '/\\' ) . '/.git/HEAD';
			if ( ! is_readable( $head_path ) ) {
				continue;
			}
			$head = trim( (string) @file_get_contents( $head_path ) ); // phpcs:ignore
			if ( strpos( $head, 'ref: ' ) === 0 ) {
				$ref      = substr( $head, 5 );
				$ref_path = rtrim( $dir, '/\\' ) . '/.git/' . $ref;
				if ( is_readable( $ref_path ) ) {
					$sha = trim( (string) @file_get_contents( $ref_path ) ); // phpcs:ignore
					if ( preg_match( '/^[0-9a-f]{40}$/', $sha ) ) {
						return $sha;
					}
				}
				$packed = rtrim( $dir, '/\\' ) . '/.git/packed-refs';
				if ( is_readable( $packed ) ) {
					$lines = file( $packed, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES );
					if ( is_array( $lines ) ) {
						foreach ( $lines as $line ) {
							if ( substr( $line, 0, 1 ) === '#' ) {
								continue;
							}
							[ $sha, $packed_ref ] = array_pad( explode( ' ', $line, 2 ), 2, '' );
							if ( $packed_ref === $ref && preg_match( '/^[0-9a-f]{40}$/', $sha ) ) {
								return $sha;
							}
						}
					}
				}
			} elseif ( preg_match( '/^[0-9a-f]{40}$/', $head ) ) {
				return $head;
			}
		}
		return null;
	}

	private function composer_lock_hash(): ?string {
		$candidates = [ ABSPATH, dirname( ABSPATH ), dirname( ABSPATH, 2 ) ];
		foreach ( $candidates as $dir ) {
			$path = rtrim( $dir, '/\\' ) . '/composer.lock';
			if ( is_readable( $path ) ) {
				$bytes = @file_get_contents( $path ); // phpcs:ignore
				if ( is_string( $bytes ) ) {
					return hash( 'sha256', $bytes );
				}
			}
		}
		return null;
	}

	private function plugin_list(): array {
		if ( ! function_exists( 'get_plugins' ) ) {
			require_once ABSPATH . 'wp-admin/includes/plugin.php';
		}
		$active          = (array) get_option( 'active_plugins', [] );
		$update_plugins  = get_site_transient( 'update_plugins' );
		$update_response = is_object( $update_plugins ) && isset( $update_plugins->response )
			? (array) $update_plugins->response
			: [];
		$out = [];
		foreach ( get_plugins() as $file => $data ) {
			$update_info = isset( $update_response[ $file ] ) ? $update_response[ $file ] : null;
			$out[] = [
				'file'             => $file,
				'slug'             => dirname( $file ) === '.' ? basename( $file, '.php' ) : dirname( $file ),
				'name'             => isset( $data['Name'] ) ? (string) $data['Name'] : '',
				'version'          => isset( $data['Version'] ) ? (string) $data['Version'] : '',
				'active'           => in_array( $file, $active, true ),
				'update_available' => $update_info !== null,
				'new_version'      => $update_info ? (string) $update_info->new_version : null,
			];
		}
		return $out;
	}

	private function theme_list(): array {
		$active_stylesheet = get_stylesheet();
		$active_template   = get_template();
		$out               = [];
		foreach ( wp_get_themes() as $stylesheet => $theme ) {
			$out[] = [
				'stylesheet' => (string) $stylesheet,
				'name'       => (string) $theme->get( 'Name' ),
				'version'    => (string) $theme->get( 'Version' ),
				'active'     => $stylesheet === $active_stylesheet || $stylesheet === $active_template,
			];
		}
		return $out;
	}
}
