<?php

declare(strict_types=1);

namespace FormConnector\Integration\Health;

/**
 * Health check system.
 * Checks system requirements, API connectivity, and form plugin status.
 */
class HealthCheck {

	/**
	 * Run all health checks.
	 */
	public function run_all(): array {
		return [
			'system' => $this->check_system(),
			'api' => $this->check_api(),
			'forms' => $this->check_forms(),
			'database' => $this->check_database(),
		];
	}

	/**
	 * Check system requirements.
	 */
	public function check_system(): array {
		$checks = [];

		// PHP Version
		$php_version = phpversion();
		$php_required = '7.4';
		$checks[] = [
			'name' => 'PHP Version',
			'status' => version_compare($php_version, $php_required, '>=') ? 'ok' : 'error',
			'value' => $php_version,
			'required' => $php_required . '+',
		];

		// WordPress Version
		$wp_version = get_bloginfo('version');
		$wp_required = '5.8';
		$checks[] = [
			'name' => 'WordPress Version',
			'status' => version_compare($wp_version, $wp_required, '>=') ? 'ok' : 'error',
			'value' => $wp_version,
			'required' => $wp_required . '+',
		];

		// cURL Extension
		$curl_enabled = function_exists('curl_init');
		$checks[] = [
			'name' => 'cURL Extension',
			'status' => $curl_enabled ? 'ok' : 'error',
			'value' => $curl_enabled ? __('Enabled', 'form-connector') : __('Disabled', 'form-connector'),
			'required' => __('Required', 'form-connector'),
		];

		// JSON Extension
		$json_enabled = function_exists('json_encode');
		$checks[] = [
			'name' => 'JSON Extension',
			'status' => $json_enabled ? 'ok' : 'error',
			'value' => $json_enabled ? __('Enabled', 'form-connector') : __('Disabled', 'form-connector'),
			'required' => __('Required', 'form-connector'),
		];

		// SSL/TLS
		$ssl_available = extension_loaded('openssl');
		$checks[] = [
			'name' => 'SSL/TLS Support',
			'status' => $ssl_available ? 'ok' : 'warning',
			'value' => $ssl_available ? __('Available', 'form-connector') : __('Not available', 'form-connector'),
			'required' => __('Recommended', 'form-connector'),
		];

		// Memory Limit
		$memory_limit = ini_get('memory_limit');
		$memory_bytes = $this->convert_to_bytes($memory_limit);
		$memory_required = 64 * 1024 * 1024; // 64MB
		$checks[] = [
			'name' => 'Memory Limit',
			'status' => $memory_bytes >= $memory_required ? 'ok' : 'warning',
			'value' => $memory_limit,
			'required' => '64M+',
		];

		return [
			'name' => __('System Requirements', 'form-connector'),
			'status' => $this->aggregate_status($checks),
			'checks' => $checks,
		];
	}

	/**
	 * Check API connectivity.
	 */
	public function check_api(): array {
		$checks = [];

		// CareHQ API Endpoint
		$api_endpoint = defined('FC_LICENSE_API_ENDPOINT') ? FC_LICENSE_API_ENDPOINT : 'https://app.formconnector.co.uk';
		$api_reachable = $this->ping_url($api_endpoint);
		
		$checks[] = [
			'name' => 'License API',
			'status' => $api_reachable ? 'ok' : 'error',
			'value' => $api_reachable ? __('Connected', 'form-connector') : __('Unreachable', 'form-connector'),
			'endpoint' => $api_endpoint,
		];

		// CareHQ CRM API (if configured)
		$carehq_api_key = get_option('fc_carehq_api_key', '');
		if (!empty($carehq_api_key)) {
			$carehq_connected = $this->test_carehq_connection();
			$checks[] = [
				'name' => 'CareHQ API',
				'status' => $carehq_connected ? 'ok' : 'error',
				'value' => $carehq_connected ? __('Connected', 'form-connector') : __('Connection failed', 'form-connector'),
			];
		} else {
			$checks[] = [
				'name' => 'CareHQ API',
				'status' => 'warning',
				'value' => __('Not configured', 'form-connector'),
			];
		}

		// WordPress REST API
		$rest_available = rest_url() && get_option('permalink_structure');
		$checks[] = [
			'name' => 'WordPress REST API',
			'status' => $rest_available ? 'ok' : 'warning',
			'value' => $rest_available ? __('Available', 'form-connector') : __('Check permalinks', 'form-connector'),
		];

		return [
			'name' => __('API Connectivity', 'form-connector'),
			'status' => $this->aggregate_status($checks),
			'checks' => $checks,
		];
	}

	/**
	 * Check supported form plugins.
	 */
	public function check_forms(): array {
		$checks = [];

		// Define supported form plugins
		$plugins = [
			[
				'name' => 'Gravity Forms',
				'class' => 'GFForms',
				'slug' => 'gravityforms',
			],
			[
				'name' => 'Forminator',
				'class' => 'Forminator',
				'slug' => 'forminator',
			],
			[
				'name' => 'WPForms',
				'class' => 'WPForms',
				'slug' => 'wpforms-lite',
			],
			[
				'name' => 'FluentForms',
				'class' => 'FluentForm\\App\\Modules\\Registerer\\Menu',
				'slug' => 'fluentform',
			],
			[
				'name' => 'Contact Form 7',
				'class' => 'WPCF7',
				'slug' => 'contact-form-7',
			],
		];

		$detected_count = 0;

		foreach ($plugins as $plugin) {
			$is_active = class_exists($plugin['class']);
			
			if ($is_active) {
				$detected_count++;
			}

			$checks[] = [
				'name' => $plugin['name'],
				'status' => $is_active ? 'ok' : 'inactive',
				'value' => $is_active ? __('Active', 'form-connector') : __('Not installed', 'form-connector'),
				'slug' => $plugin['slug'],
			];
		}

		return [
			'name' => __('Form Plugins', 'form-connector'),
			'status' => $detected_count > 0 ? 'ok' : 'warning',
			'detected_count' => $detected_count,
			'checks' => $checks,
		];
	}

	/**
	 * Check database tables and options.
	 */
	public function check_database(): array {
		global $wpdb;
		$checks = [];

		// Check if we can write to options table
		$test_option = 'fc_health_check_test';
		$write_test = update_option($test_option, time());
		$read_test = get_option($test_option);
		delete_option($test_option);

		$checks[] = [
			'name' => 'Options Table',
			'status' => ($write_test && $read_test) ? 'ok' : 'error',
			'value' => ($write_test && $read_test) ? __('Writable', 'form-connector') : __('Write failed', 'form-connector'),
		];

		// Check transients
		$transient_test = 'fc_health_check_transient';
		set_transient($transient_test, time(), 60);
		$transient_read = get_transient($transient_test);
		delete_transient($transient_test);

		$checks[] = [
			'name' => 'Transients',
			'status' => $transient_read ? 'ok' : 'warning',
			'value' => $transient_read ? __('Working', 'form-connector') : __('May be disabled', 'form-connector'),
		];

		// Check existing plugin data
		$license_data = get_option('fc_license_data', null);
		$has_data = !empty($license_data);

		$checks[] = [
			'name' => 'Plugin Data',
			'status' => 'ok',
			'value' => $has_data ? __('Found', 'form-connector') : __('Fresh install', 'form-connector'),
		];

		return [
			'name' => __('Database', 'form-connector'),
			'status' => $this->aggregate_status($checks),
			'checks' => $checks,
		];
	}

	/**
	 * Ping a URL to check if it's reachable.
	 */
	private function ping_url(string $url): bool {
		$response = wp_remote_head($url, [
			'timeout' => 5,
			'sslverify' => true,
		]);

		if (is_wp_error($response)) {
			// Try without SSL verification
			$response = wp_remote_head($url, [
				'timeout' => 5,
				'sslverify' => false,
			]);
		}

		return !is_wp_error($response) && wp_remote_retrieve_response_code($response) < 500;
	}

	/**
	 * Test CareHQ API connection.
	 */
	private function test_carehq_connection(): bool {
		// Placeholder - implement actual CareHQ API test
		return false;
	}

	/**
	 * Convert PHP memory limit to bytes.
	 */
	private function convert_to_bytes(string $value): int {
		$value = trim($value);
		$last = strtolower($value[strlen($value) - 1]);
		$value = (int) $value;

		switch ($last) {
			case 'g':
				$value *= 1024;
				// fall through
			case 'm':
				$value *= 1024;
				// fall through
			case 'k':
				$value *= 1024;
		}

		return $value;
	}

	/**
	 * Aggregate status from multiple checks.
	 */
	private function aggregate_status(array $checks): string {
		$has_error = false;
		$has_warning = false;

		foreach ($checks as $check) {
			if ($check['status'] === 'error') {
				$has_error = true;
			} elseif ($check['status'] === 'warning') {
				$has_warning = true;
			}
		}

		if ($has_error) {
			return 'error';
		}

		if ($has_warning) {
			return 'warning';
		}

		return 'ok';
	}
}
