<?php
/**
 * Domain checks and diagnostic helpers.
 *
 * @package MailDoctor
 */

namespace MailDoctor;

use MailDoctor\Helpers\DNS;
use WP_Error;

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

/**
 * Provides domain health checks and log inspection utilities.
 */
class Checks {


	/**
	 * Produce SPF/DKIM/DMARC summary for a domain.
	 *
	 * @param string $domain Domain name.
	 * @return array<string, array<string, string>>
	 */
	public static function dns_summary( string $domain ): array {
		$domain = strtolower( trim( $domain ) );

		if ( empty( $domain ) ) {
			return self::empty_summary();
		}

		return array(
			'spf'     => self::check_spf( $domain ),
			'dkim'    => self::check_dkim( $domain ),
			'dmarc'   => self::check_dmarc( $domain ),
			'bimi'    => self::check_bimi( $domain ),
			'mta_sts' => self::check_mta_sts( $domain ),
			'tls_rpt' => self::check_tls_rpt( $domain ),
		);
	}

	/**
	 * Gather queue statistics.
	 *
	 * @return array<string, int>
	 */
	public static function queue_stats(): array {
		global $wpdb;

		$table = Logger::table_name();
		// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
		$rows = $wpdb->get_results( "SELECT status, COUNT(*) as total FROM {$table} GROUP BY status", ARRAY_A );

		$stats = array(
			'queued'      => 0,
			'sent'        => 0,
			'failed'      => 0,
			'quarantined' => 0,
		);

		if ( ! empty( $rows ) ) {
			foreach ( $rows as $row ) {
				$status = $row['status'] ?? '';
				$count  = (int) ( $row['total'] ?? 0 );

				if ( isset( $stats[ $status ] ) ) {
					$stats[ $status ] = $count;
				}
			}
		}

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Stat aggregation query.
		$quarantined = $wpdb->get_var(
			$wpdb->prepare(
				// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared
				"SELECT COUNT(*) FROM {$table} WHERE status IN ('failed','queued') AND payload LIKE %s",
				'%"quarantined":true%'
			)
		);

		if ( null !== $quarantined ) {
			$stats['quarantined'] = (int) $quarantined;
		}

		return $stats;
	}

	/**
	 * Check SPF record presence.
	 *
	 * @param string $domain Domain.
	 * @return array<string, string>
	 */
	protected static function check_spf( string $domain ): array {
		$result = DNS::get_txt( $domain );

		if ( $result instanceof WP_Error ) {
			return array(
				'status'  => 'unavailable',
				'message' => $result->get_error_message(),
				'value'   => '',
			);
		}

		foreach ( $result as $record ) {
			if ( stripos( $record, 'v=spf1' ) === 0 ) {
				return array(
					'status'  => 'present',
					'message' => __( 'SPF record detected.', 'mail-doctor' ),
					'value'   => $record,
				);
			}
		}

		return array(
			'status'  => 'missing',
			'message' => __( 'No SPF record found. Configure SPF to authorize your sending IPs.', 'mail-doctor' ),
			'value'   => '',
		);
	}

	/**
	 * Attempt to detect DKIM record presence.
	 *
	 * @param string $domain Domain.
	 * @return array<string, string>
	 */
	protected static function check_dkim( string $domain ): array {
		$selector = 'default';
		$result   = DNS::get_txt( $selector . '._domainkey.' . $domain );

		if ( $result instanceof WP_Error ) {
			return array(
				'status'  => 'unavailable',
				'message' => __( 'DKIM lookup unavailable. Confirm DKIM with your email provider.', 'mail-doctor' ),
				'value'   => '',
			);
		}

		foreach ( $result as $record ) {
			if ( stripos( $record, 'v=dkim1' ) === 0 ) {
				return array(
					'status'  => 'present',
					'message' => sprintf(
						/* translators: %s: DKIM selector used. */
						__( 'DKIM record detected using selector "%s".', 'mail-doctor' ),
						$selector
					),
					'value'   => $record,
				);
			}
		}

		return array(
			'status'  => 'warning',
			'message' => __( 'DKIM not found for selector "default". If you use a custom selector, update the guides accordingly.', 'mail-doctor' ),
			'value'   => '',
		);
	}

	/**
	 * Detect DMARC policy presence.
	 *
	 * @param string $domain Domain.
	 * @return array<string, string>
	 */
	protected static function check_dmarc( string $domain ): array {
		$result = DNS::get_txt( '_dmarc.' . $domain );

		if ( $result instanceof WP_Error ) {
			return array(
				'status'  => 'unavailable',
				'message' => __( 'DMARC lookup unavailable. Configure DMARC with your DNS provider.', 'mail-doctor' ),
				'value'   => '',
			);
		}

		foreach ( $result as $record ) {
			if ( stripos( $record, 'v=dmarc1' ) === 0 ) {
				return array(
					'status'  => 'present',
					'message' => __( 'DMARC policy detected.', 'mail-doctor' ),
					'value'   => $record,
				);
			}
		}

		return array(
			'status'  => 'missing',
			'message' => __( 'No DMARC policy detected. Enable DMARC to monitor spoofing attempts.', 'mail-doctor' ),
			'value'   => '',
		);
	}

	/**
	 * Provide default placeholder summary.
	 *
	 * @return array<string, array<string, string>>
	 */
	protected static function empty_summary(): array {
		return array(
			'spf'     => array(
				'status'  => 'unknown',
				'message' => __( 'Domain unavailable.', 'mail-doctor' ),
				'value'   => '',
			),
			'dkim'    => array(
				'status'  => 'unknown',
				'message' => __( 'Domain unavailable.', 'mail-doctor' ),
				'value'   => '',
			),
			'dmarc'   => array(
				'status'  => 'unknown',
				'message' => __( 'Domain unavailable.', 'mail-doctor' ),
				'value'   => '',
			),
			'bimi'    => array(
				'status'  => 'unknown',
				'message' => __( 'Domain unavailable.', 'mail-doctor' ),
				'value'   => '',
			),
			'mta_sts' => array(
				'status'  => 'unknown',
				'message' => __( 'Domain unavailable.', 'mail-doctor' ),
				'value'   => '',
			),
			'tls_rpt' => array(
				'status'  => 'unknown',
				'message' => __( 'Domain unavailable.', 'mail-doctor' ),
				'value'   => '',
			),
		);
	}

	/**
	 * Check BIMI record.
	 *
	 * @param string $domain Domain name.
	 * @return array<string, string>
	 */
	protected static function check_bimi( string $domain ): array {
		$selector = 'default._bimi.' . $domain;
		$result   = DNS::get_txt( $selector );

		if ( $result instanceof WP_Error ) {
			return array(
				'status'  => 'unavailable',
				'message' => __( 'BIMI lookup unavailable. Publish BIMI records with your DNS provider.', 'mail-doctor' ),
				'value'   => '',
			);
		}

		foreach ( $result as $record ) {
			if ( stripos( $record, 'v=BIMI1' ) === 0 ) {
				return array(
					'status'  => 'present',
					'message' => __( 'BIMI record detected.', 'mail-doctor' ),
					'value'   => $record,
				);
			}
		}

		return array(
			'status'  => 'warning',
			'message' => __( 'No BIMI record detected. Consider adding BIMI for inbox branding.', 'mail-doctor' ),
			'value'   => '',
		);
	}

	/**
	 * Check MTA-STS record presence.
	 *
	 * @param string $domain Domain name.
	 * @return array<string, string>
	 */
	protected static function check_mta_sts( string $domain ): array {
		$result = DNS::get_txt( '_mta-sts.' . $domain );

		if ( $result instanceof WP_Error ) {
			return array(
				'status'  => 'unavailable',
				'message' => __( 'MTA-STS lookup unavailable. Configure MTA-STS TXT and policy files for stricter TLS.', 'mail-doctor' ),
				'value'   => '',
			);
		}

		foreach ( $result as $record ) {
			if ( stripos( $record, 'v=STSv1' ) === 0 ) {
				return array(
					'status'  => 'present',
					'message' => __( 'MTA-STS TXT record detected.', 'mail-doctor' ),
					'value'   => $record,
				);
			}
		}

		return array(
			'status'  => 'warning',
			'message' => __( 'No MTA-STS record found. Add _mta-sts TXT and HTTPS policy for stricter inbound TLS.', 'mail-doctor' ),
			'value'   => '',
		);
	}

	/**
	 * Check TLS-RPT presence.
	 *
	 * @param string $domain Domain.
	 * @return array<string, string>
	 */
	protected static function check_tls_rpt( string $domain ): array {
		$result = DNS::get_txt( '_smtp._tls.' . $domain );

		if ( $result instanceof WP_Error ) {
			return array(
				'status'  => 'unavailable',
				'message' => __( 'TLS-RPT lookup unavailable. Configure TLS reporting to receive TLS failure reports.', 'mail-doctor' ),
				'value'   => '',
			);
		}

		foreach ( $result as $record ) {
			if ( stripos( $record, 'v=TLSRPTv1' ) === 0 ) {
				return array(
					'status'  => 'present',
					'message' => __( 'TLS-RPT record detected.', 'mail-doctor' ),
					'value'   => $record,
				);
			}
		}

		return array(
			'status'  => 'warning',
			'message' => __( 'No TLS-RPT record found. Add _smtp._tls TXT to receive TLS failure reports.', 'mail-doctor' ),
			'value'   => '',
		);
	}
}
