<?php

declare(strict_types=1);

namespace FormConnector\Features\Logs;

use FormConnector\Core\Settings\Settings;
use FormConnector\Core\Utils\Debug;
use Throwable;

/**
 * Scheduled cleanup of old log entries.
 *
 * Reads the `log_retention_days` setting and runs a daily WP-Cron job
 * that deletes log rows older than that age. A value of 0 keeps logs
 * forever (the cron job becomes a no-op).
 */
class RetentionCron {

	public const CRON_HOOK = 'fc_logs_retention_cleanup';

	/**
	 * Register hooks. Call from plugin bootstrap.
	 */
	public static function register(): void {
		add_action(self::CRON_HOOK, [self::class, 'run']);
		add_action('init', [self::class, 'maybe_schedule']);
	}

	/**
	 * Ensure the daily cron event is scheduled.
	 */
	public static function maybe_schedule(): void {
		if (!wp_next_scheduled(self::CRON_HOOK)) {
			// Schedule first run ~5 minutes from now so it doesn't fight other admin work.
			wp_schedule_event(time() + 300, 'daily', self::CRON_HOOK);
		}
	}

	/**
	 * Remove the scheduled cron event (called from deactivation).
	 */
	public static function unschedule(): void {
		$ts = wp_next_scheduled(self::CRON_HOOK);
		if ($ts) {
			wp_unschedule_event($ts, self::CRON_HOOK);
		}
	}

	/**
	 * Execute the retention purge.
	 *
	 * Returns the number of rows deleted (for testing). Silently
	 * returns 0 when retention is disabled or anything throws.
	 */
	public static function run(): int {
		try {
			if (!class_exists(Settings::class) || !class_exists(Logs::class)) {
				return 0;
			}

			$settings = Settings::get_instance();
			$logs = Logs::get_instance();

			// 1. PII redaction (runs first so retention deletion can still
			// observe the cutoff window cleanly).
			$redact_days = (int) $settings->get('pii_redact_days');
			if ($redact_days > 0) {
				$redacted = $logs->redact_pii_older_than($redact_days);
				if ($redacted > 0 && class_exists(Debug::class)) {
					Debug::log(sprintf(
						'Logs PII redaction scrubbed %d rows (older than %d days).',
						$redacted,
						$redact_days
					));
				}
			}

			// 2. Retention purge.
			$days = (int) $settings->get('log_retention_days');
			if ($days <= 0) {
				return 0;
			}

			$deleted = $logs->delete_old_logs($days);

			if ($deleted > 0 && class_exists(Debug::class)) {
				Debug::log(
					sprintf('Logs retention cleanup deleted %d rows (older than %d days).', $deleted, $days)
				);
			}

			return $deleted;
		} catch (Throwable $e) {
			if (class_exists(Debug::class)) {
				Debug::error('Logs retention cleanup failed: ' . $e->getMessage());
			}
			return 0;
		}
	}
}
