<?php
/**
 * TamRank_Outdated_Scanner
 *
 * Batch scanner: iterates all published posts/pages, calls
 * TamRank_Outdated_Detector::detect() on each, and persists
 * results to post meta '_tamrank_outdated_detections'.
 *
 * Meta key: _tamrank_outdated_detections
 * Meta value: serialized array (WordPress handles serialization via update_post_meta)
 *   Each element: [ 'field' => string, 'year' => int, 'value' => string ]
 *
 * AJAX action: tam_rank_scan_outdated
 *   POST params:
 *     nonce  (string) — wp_nonce 'tam_rank_scan_outdated_nonce'
 *     offset (int)    — 0-based batch offset (default 0)
 *   Response (success):
 *     { scanned: int, found: int, has_more: bool, next_offset: int, total: int }
 *   Response (error):
 *     { message: string }
 */

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

class TamRank_Outdated_Scanner {

	const META_KEY  = '_tamrank_outdated_detections';
	const NONCE_KEY = 'tam_rank_scan_outdated_nonce';
	const BATCH     = 50;

	/** @var TamRank_Outdated_Scanner|null */
	private static $instance = null;

	public static function get_instance() {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	private function __construct() {
		add_action( 'wp_ajax_tam_rank_scan_outdated', array( $this, 'ajax_scan_outdated' ) );
	}

	/**
	 * AJAX handler: scan one batch of posts.
	 */
	public function ajax_scan_outdated() {
		// Security
		if ( ! check_ajax_referer( self::NONCE_KEY, 'nonce', false ) ) {
			wp_send_json_error( array( 'message' => tamrank__('error_nonce_invalid', 'Invalid security token. Please refresh the page.'), 'code' => 'nonce_invalid' ) );
			return;
		}
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => tamrank__('error_permission_denied', 'You do not have permission for this action.'), 'code' => 'permission_denied' ) );
			return;
		}

		$offset = isset( $_POST['offset'] ) ? max( 0, (int) $_POST['offset'] ) : 0;

		// Query one batch of published post IDs
		$query = new WP_Query( array(
			'post_type'      => array( 'post', 'page' ),
			'post_status'    => 'publish',
			'posts_per_page' => self::BATCH,
			'offset'         => $offset,
			'fields'         => 'ids',
			'no_found_rows'  => false, // need found_posts to determine has_more
		) );

		$scanned = 0;
		$found   = 0;

		foreach ( $query->posts as $post_id ) {
			$scanned++;
			$detections = TamRank_Outdated_Detector::detect( (int) $post_id );

			if ( ! empty( $detections ) ) {
				update_post_meta( $post_id, self::META_KEY, $detections );
				$found++;
			} else {
				delete_post_meta( $post_id, self::META_KEY );
			}
		}

		$has_more    = ( $offset + self::BATCH ) < (int) $query->found_posts;
		$next_offset = $offset + self::BATCH;

		if ( ! $has_more ) {
			set_transient( 'tamrank_outdated_scan_done', 1, DAY_IN_SECONDS );
		}

		wp_send_json_success( array(
			'scanned'     => $scanned,
			'found'       => $found,
			'has_more'    => $has_more,
			'next_offset' => $next_offset,
			'total'       => (int) $query->found_posts,
		) );
	}

	/**
	 * Retrieve stored detections for a post.
	 *
	 * @param int $post_id
	 * @return array
	 */
	public static function get_detections( $post_id ) {
		$raw = get_post_meta( $post_id, self::META_KEY, true );
		return is_array( $raw ) ? $raw : array();
	}

	/**
	 * Get all posts that have stored detections.
	 *
	 * Used by Phase 3 (Dashboard Integratie) to build "Jouw SEO Taken".
	 *
	 * @return array Array of post IDs with '_tamrank_outdated_detections' meta set.
	 */
	public static function get_flagged_post_ids() {
		global $wpdb;
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery -- direct query on a custom plugin meta read (postmeta); admin-context read, caching not applicable
		$results = $wpdb->get_col(
			$wpdb->prepare(
				"SELECT DISTINCT post_id
				 FROM {$wpdb->postmeta}
				 WHERE meta_key = %s",
				self::META_KEY
			)
		);
		return array_map( 'intval', $results );
	}
}
