<?php
/**
 * Spam Protection Settings Tab
 *
 * @package AmbassadorHub\Admin\Settings\Tabs
 */

namespace AmbassadorHub\Admin\Settings\Tabs;

use AmbassadorHub\Admin\Settings\AbstractTab;
use AmbassadorHub\Admin\Settings\Fields;
use AmbassadorHub\Spam\SpamShield;

use function __;
use function admin_url;
use function esc_html;
use function esc_html__;
use function esc_url;
use function get_option;
use function settings_fields;
use function do_settings_sections;
use function submit_button;
use function wp_nonce_field;
use function wp_date;

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

/**
 * Spam Protection settings tab.
 *
 * Controls for the built-in, no-external-service anti-spam measures applied
 * to the public signup, donation, and team-invite forms (see
 * AmbassadorHub\Spam\SpamShield). Everything here works with zero
 * configuration — there is nothing to sign up for and nothing that contacts
 * a third party.
 */
final class SpamProtectionTab extends AbstractTab {

	/**
	 * Human-readable labels for the diagnostic log's reason codes.
	 *
	 * @var array<string,string>
	 */
	private const REASON_LABELS = array(
		'honeypot'        => 'Hidden field was filled in (bot behavior)',
		'timing_missing'  => 'Missing timing check',
		'timing_invalid'  => 'Invalid timing check',
		'timing_too_fast' => 'Submitted faster than a human plausibly could',
		'rate_limited'    => 'Too many submissions from this visitor',
		'blocked_email'   => 'Disposable or blocked email domain',
		'too_many_links'  => 'Message contained too many links',
	);

	/**
	 * Constructor.
	 */
	public function __construct() {
		$this->id       = 'spam';
		$this->label    = __( 'Spam Protection', 'ambassadorhub' );
		$this->priority = 40;
	}

	/**
	 * Render the Spam Protection tab content.
	 *
	 * @return void
	 */
	public function render(): void {
		?>
		<p class="description">
			<?php esc_html_e( 'Reduces automated spam on the public signup, donation, and team-invite forms using only built-in, self-hosted checks — no CAPTCHA provider, no external service, and nothing is sent off this site.', 'ambassadorhub' ); ?>
		</p>

		<form method="post" action="options.php">
			<?php settings_fields( 'ambh_spam' ); ?>
			<?php do_settings_sections( 'ambh_spam' ); ?>

			<h3><?php esc_html_e( 'Honeypot &amp; timing check', 'ambassadorhub' ); ?></h3>
			<p class="description"><?php esc_html_e( 'Adds an invisible field real visitors never see, and measures how quickly the form was submitted after it loaded. Both are self-hosted and invisible to real visitors.', 'ambassadorhub' ); ?></p>
			<table class="form-table" role="presentation">
				<tbody>
					<?php
					Fields::checkbox(
						'ambh_spam_honeypot_enabled',
						esc_html__( 'Honeypot & timing check', 'ambassadorhub' ),
						esc_html__( 'Enable on the signup and donation forms', 'ambassadorhub' )
					);
					Fields::text(
						'ambh_spam_min_submit_seconds',
						esc_html__( 'Minimum seconds before submission', 'ambassadorhub' ),
						esc_html__( 'Submissions faster than this are treated as automated. 2-3 seconds is safe for real visitors.', 'ambassadorhub' ),
						'number',
						array(
							'min'  => '0',
							'step' => '1',
						)
					);
					?>
				</tbody>
			</table>

			<h3><?php esc_html_e( 'Rate limiting', 'ambassadorhub' ); ?></h3>
			<p class="description"><?php esc_html_e( 'Limits signups per hour and donation bursts per 10 minutes for a single visitor. Donation emails also have a separate hourly limit, so shared networks such as events are less likely to block legitimate donors. IP addresses and emails are stored only as one-way hashes.', 'ambassadorhub' ); ?></p>
			<table class="form-table" role="presentation">
				<tbody>
					<?php
					Fields::checkbox(
						'ambh_spam_rate_limiting_enabled',
						esc_html__( 'Rate limiting', 'ambassadorhub' ),
						esc_html__( 'Enable on the signup and donation forms', 'ambassadorhub' )
					);
					Fields::text(
						'ambh_spam_signup_rate_limit',
						esc_html__( 'Max signups per hour per visitor', 'ambassadorhub' ),
						'',
						'number',
						array(
							'min'  => '1',
							'step' => '1',
						)
					);
					Fields::text(
						'ambh_spam_donation_rate_limit',
						esc_html__( 'Max donation burst submissions per 10 minutes per visitor', 'ambassadorhub' ),
						'',
						'number',
						array(
							'min'  => '1',
							'step' => '1',
						)
					);
					?>
				</tbody>
			</table>

			<h3><?php esc_html_e( 'Blocked email domains', 'ambassadorhub' ); ?></h3>
			<p class="description"><?php esc_html_e( 'Rejects a small built-in list of well-known disposable/throwaway email providers on signup and donation forms. Add your own domains below, one per line.', 'ambassadorhub' ); ?></p>
			<table class="form-table" role="presentation">
				<tbody>
					<?php
					Fields::checkbox(
						'ambh_spam_email_filter_enabled',
						esc_html__( 'Blocked email domains', 'ambassadorhub' ),
						esc_html__( 'Enable on the signup and donation forms', 'ambassadorhub' )
					);
					Fields::textarea(
						'ambh_spam_blocked_email_domains',
						esc_html__( 'Additional blocked domains', 'ambassadorhub' ),
						esc_html__( 'One domain per line, e.g. example.com. Merged with the built-in disposable-email list.', 'ambassadorhub' ),
						5,
						"example.com\nspam-domain.net"
					);
					?>
				</tbody>
			</table>

			<h3><?php esc_html_e( 'Message link filter', 'ambassadorhub' ); ?></h3>
			<p class="description"><?php esc_html_e( 'Flags the optional donation message field when it contains more links than allowed — a common sign of link spam.', 'ambassadorhub' ); ?></p>
			<table class="form-table" role="presentation">
				<tbody>
					<?php
					Fields::checkbox(
						'ambh_spam_content_filter_enabled',
						esc_html__( 'Message link filter', 'ambassadorhub' ),
						esc_html__( 'Enable on the donation message field', 'ambassadorhub' )
					);
					Fields::text(
						'ambh_spam_max_links_in_message',
						esc_html__( 'Max links allowed in a message', 'ambassadorhub' ),
						'',
						'number',
						array(
							'min'  => '0',
							'step' => '1',
						)
					);
					?>
				</tbody>
			</table>

			<?php submit_button(); ?>
		</form>

		<hr />

		<h3><?php esc_html_e( 'Recently blocked attempts', 'ambassadorhub' ); ?></h3>
		<p class="description"><?php esc_html_e( 'The most recent submissions blocked by the checks above. Only a hash of the visitor\'s IP address is kept — never the address itself.', 'ambassadorhub' ); ?></p>

		<?php $this->render_log_table(); ?>

		<form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" style="margin-top: 1em;">
			<?php wp_nonce_field( 'ambh_clear_spam_log', 'ambh_clear_spam_log_nonce' ); ?>
			<input type="hidden" name="action" value="ambh_clear_spam_log">
			<?php submit_button( __( 'Clear log', 'ambassadorhub' ), 'secondary', 'ambh_clear_spam_log_submit', false ); ?>
		</form>
		<?php
	}

	/**
	 * Render the diagnostic log as a list table.
	 *
	 * @return void
	 */
	private function render_log_table(): void {
		$log = SpamShield::get_log();

		if ( empty( $log ) ) {
			echo '<p>' . esc_html__( 'No blocked attempts recorded yet.', 'ambassadorhub' ) . '</p>';
			return;
		}
		?>
		<table class="wp-list-table widefat fixed striped">
			<thead>
				<tr>
					<th scope="col"><?php esc_html_e( 'Time', 'ambassadorhub' ); ?></th>
					<th scope="col"><?php esc_html_e( 'Form', 'ambassadorhub' ); ?></th>
					<th scope="col"><?php esc_html_e( 'Reason', 'ambassadorhub' ); ?></th>
					<th scope="col"><?php esc_html_e( 'Visitor (hashed)', 'ambassadorhub' ); ?></th>
				</tr>
			</thead>
			<tbody>
				<?php foreach ( $log as $entry ) : ?>
					<tr>
						<td><?php echo esc_html( wp_date( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), (int) ( $entry['time'] ?? 0 ) ) ); ?></td>
						<td><?php echo esc_html( (string) ( $entry['form'] ?? '' ) ); ?></td>
						<td><?php echo esc_html( $this->reason_label( (string) ( $entry['reason'] ?? '' ) ) ); ?></td>
						<td><code><?php echo esc_html( (string) ( $entry['ip_hash'] ?? '' ) ); ?></code></td>
					</tr>
				<?php endforeach; ?>
			</tbody>
		</table>
		<?php
	}

	/**
	 * Map a reason code to its human-readable label.
	 *
	 * @param string $reason Reason code.
	 *
	 * @return string
	 */
	private function reason_label( string $reason ): string {
		return self::REASON_LABELS[ $reason ] ?? $reason;
	}
}
