<?php
/**
 * Site Health integration for Mail Doctor.
 *
 * @package MailDoctor
 */

namespace MailDoctor;

use MailDoctor\Helpers\Settings;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Adds custom Site Health checks.
 */
class SiteHealth {

	/**
	 * Initialize hooks.
	 *
	 * @return void
	 */
	public static function init(): void {
		add_filter( 'site_status_tests', array( __CLASS__, 'register_tests' ) );
	}

	/**
	 * Register Mail Doctor Site Health tests.
	 *
	 * @param array<string, array<string, mixed>> $tests Existing tests.
	 * @return array<string, array<string, mixed>>
	 */
	public static function register_tests( array $tests ): array {
		if ( ! current_user_can( 'manage_woocommerce' ) ) {
			return $tests;
		}

		$tests['direct']['mail_doctor_smtp'] = array(
			'label' => __( 'Mail Doctor SMTP connectivity', 'mail-doctor' ),
			'test'  => array( __CLASS__, 'test_smtp' ),
		);

		$tests['direct']['mail_doctor_dns'] = array(
			'label' => __( 'Mail Doctor domain records', 'mail-doctor' ),
			'test'  => array( __CLASS__, 'test_dns' ),
		);

		$tests['direct']['mail_doctor_cron'] = array(
			'label' => __( 'Mail Doctor retry scheduler', 'mail-doctor' ),
			'test'  => array( __CLASS__, 'test_cron' ),
		);

		$tests['direct']['mail_doctor_queue'] = array(
			'label' => __( 'Mail Doctor email queue size', 'mail-doctor' ),
			'test'  => array( __CLASS__, 'test_queue' ),
		);

		return $tests;
	}

	/**
	 * Test SMTP readiness.
	 *
	 * @return array<string, mixed>
	 */
	public static function test_smtp(): array {
		$settings = Settings::all();

		if ( empty( $settings['smtp_host'] ) || empty( $settings['smtp_username'] ) ) {
			return array(
				'label'       => __( 'Mail Doctor SMTP connectivity', 'mail-doctor' ),
				'status'      => 'recommended',
				'description' => __( 'SMTP host or credentials have not been configured. Complete the Mail Doctor setup wizard or enter SMTP settings on the Mail Doctor settings tab.', 'mail-doctor' ),
				'actions'     => self::settings_action(),
				'test'        => 'mail_doctor_smtp',
			);
		}

		$result = Mailer::test_connection();

		if ( $result['success'] ) {
			return array(
				'label'       => __( 'Mail Doctor SMTP connectivity', 'mail-doctor' ),
				'status'      => 'good',
				'description' => __( 'SMTP connection succeeded using the configured provider.', 'mail-doctor' ),
				'test'        => 'mail_doctor_smtp',
			);
		}

		return array(
			'label'       => __( 'Mail Doctor SMTP connectivity', 'mail-doctor' ),
			'status'      => 'recommended',
			'description' => sprintf(
				/* translators: %s: error message from SMTP test */
				__( 'Mail Doctor was unable to connect to the SMTP server: %s', 'mail-doctor' ),
				isset( $result['message'] ) ? esc_html( $result['message'] ) : __( 'Unknown error.', 'mail-doctor' )
			),
			'actions'     => self::settings_action(),
			'test'        => 'mail_doctor_smtp',
		);
	}

	/**
	 * Test DNS state.
	 *
	 * @return array<string, mixed>
	 */
	public static function test_dns(): array {
		$settings = Settings::all();
		$domain   = '';

		if ( ! empty( $settings['from_email'] ) && false !== strpos( $settings['from_email'], '@' ) ) {
			$parts  = explode( '@', $settings['from_email'] );
			$domain = end( $parts );
		}

		if ( empty( $domain ) ) {
			return array(
				'label'       => __( 'Mail Doctor domain records', 'mail-doctor' ),
				'status'      => 'recommended',
				'description' => __( 'The From email is not set, so Mail Doctor cannot verify SPF, DKIM, or DMARC records.', 'mail-doctor' ),
				'actions'     => self::settings_action(),
				'test'        => 'mail_doctor_dns',
			);
		}

		$dns = Checks::dns_summary( $domain );

		$missing = array();
		foreach ( $dns as $key => $record ) {
			if ( in_array( $record['status'], array( 'missing', 'warning', 'unavailable' ), true ) ) {
				$missing[] = strtoupper( $key );
			}
		}

		if ( empty( $missing ) ) {
			return array(
				'label'       => __( 'Mail Doctor domain records', 'mail-doctor' ),
				'status'      => 'good',
				'description' => __( 'SPF, DKIM, and DMARC records are present for the sending domain.', 'mail-doctor' ),
				'test'        => 'mail_doctor_dns',
			);
		}

		return array(
			'label'       => __( 'Mail Doctor domain records', 'mail-doctor' ),
			'status'      => 'recommended',
			'description' => sprintf(
				/* translators: %s: list of record types. */
				__( 'Mail Doctor could not detect the following DNS records: %s. Configure them with your DNS provider for better deliverability.', 'mail-doctor' ),
				esc_html( implode( ', ', $missing ) )
			),
			'actions'     => array(
				'mail-doctor-guides' => array(
					'label' => __( 'Open Mail Doctor Guides', 'mail-doctor' ),
					'url'   => add_query_arg(
						array(
							'page' => Admin::PAGE_SLUG,
							'tab'  => 'guides',
						),
						admin_url( 'admin.php' )
					),
				),
			),
			'test'        => 'mail_doctor_dns',
		);
	}

	/**
	 * Test retry cron scheduling.
	 *
	 * @return array<string, mixed>
	 */
	public static function test_cron(): array {
		$next = wp_next_scheduled( Retry::CRON_HOOK );

		if ( ! $next ) {
			return array(
				'label'       => __( 'Mail Doctor retry scheduler', 'mail-doctor' ),
				'status'      => 'recommended',
				'description' => __( 'The Mail Doctor retry task is not scheduled. Verify WP-Cron is working or re-save the plugin settings.', 'mail-doctor' ),
				'actions'     => self::settings_action(),
				'test'        => 'mail_doctor_cron',
			);
		}

		$now = time();

		if ( $next < ( $now - 300 ) ) {
			return array(
				'label'       => __( 'Mail Doctor retry scheduler', 'mail-doctor' ),
				'status'      => 'recommended',
				'description' => __( 'The Mail Doctor retry event is overdue. Trigger wp-cron.php manually or ensure your server can reach wp-cron.', 'mail-doctor' ),
				'test'        => 'mail_doctor_cron',
			);
		}

		return array(
			'label'       => __( 'Mail Doctor retry scheduler', 'mail-doctor' ),
			'status'      => 'good',
			'description' => __( 'The retry worker is scheduled and will process failed emails automatically.', 'mail-doctor' ),
			'test'        => 'mail_doctor_cron',
		);
	}

	/**
	 * Test queue size.
	 *
	 * @return array<string, mixed>
	 */
	public static function test_queue(): array {
		$stats  = Checks::queue_stats();
		$failed = (int) ( $stats['failed'] ?? 0 );
		$queued = (int) ( $stats['queued'] ?? 0 );

		if ( 0 === $failed && 0 === $queued ) {
			return array(
				'label'       => __( 'Mail Doctor email queue size', 'mail-doctor' ),
				'status'      => 'good',
				'description' => __( 'There are no pending or failed emails in the Mail Doctor log.', 'mail-doctor' ),
				'test'        => 'mail_doctor_queue',
			);
		}

		$status  = ( $failed > 5 ) ? 'critical' : 'recommended';
		$message = ( $failed > 0 )
			? __( 'Failed emails are waiting to be retried.', 'mail-doctor' )
			: __( 'Queued emails are waiting to be processed.', 'mail-doctor' );

		return array(
			'label'       => __( 'Mail Doctor email queue size', 'mail-doctor' ),
			'status'      => $status,
			'description' => sprintf(
				/* translators: 1: failed count, 2: queued count */
				__( '%1$d failed and %2$d queued emails detected. %3$s', 'mail-doctor' ),
				$failed,
				$queued,
				$message
			),
			'actions'     => array(
				'mail-doctor-logs' => array(
					'label' => __( 'View Mail Doctor logs', 'mail-doctor' ),
					'url'   => add_query_arg(
						array(
							'page' => Admin::PAGE_SLUG,
							'tab'  => 'logs',
						),
						admin_url( 'admin.php' )
					),
				),
			),
			'test'        => 'mail_doctor_queue',
		);
	}

	/**
	 * Action array linking to settings.
	 *
	 * @return array<string, array<string, string>>
	 */
	protected static function settings_action(): array {
		return array(
			'mail-doctor-settings' => array(
				'label' => __( 'Open Mail Doctor settings', 'mail-doctor' ),
				'url'   => add_query_arg(
					array(
						'page' => Admin::PAGE_SLUG,
						'tab'  => 'settings',
					),
					admin_url( 'admin.php' )
				),
			),
		);
	}
}
