<?php
/**
 * Large-site / activation load controls — stagger crons, timeline cache, batch caps.
 *
 * @package Newsroom_AI_Assistant
 */

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

if ( ! function_exists( 'newsai_large_site_post_threshold' ) ) {
	/**
	 * Published post count above which auto-timeline and tighter batches apply.
	 *
	 * @return int
	 */
	function newsai_large_site_post_threshold() {
		return (int) apply_filters( 'newsai_large_site_post_threshold', 5000 );
	}
}

if ( ! function_exists( 'newsai_published_post_count' ) ) {
	/**
	 * Cached publish count for post type "post".
	 *
	 * @return int
	 */
	function newsai_published_post_count() {
		static $count = null;
		if ( null !== $count ) {
			return $count;
		}
		$counts = wp_count_posts( 'post' );
		$count  = ( isset( $counts->publish ) ) ? (int) $counts->publish : 0;
		return $count;
	}
}

if ( ! function_exists( 'newsai_is_large_site' ) ) {
	/**
	 * True when explicit large-site mode is on or publish volume exceeds threshold.
	 *
	 * @return bool
	 */
	function newsai_is_large_site() {
		if ( newsai_large_site_mode_enabled() ) {
			return true;
		}
		return newsai_published_post_count() >= newsai_large_site_post_threshold();
	}
}

if ( ! function_exists( 'newsai_large_site_mode_enabled' ) ) {
	/**
	 * Explicit “Large site mode” checkbox in settings (not auto-detect by post count).
	 *
	 * @return bool
	 */
	function newsai_large_site_mode_enabled() {
		return get_option( 'newsai_large_site_mode', 'no' ) === 'yes';
	}
}

if ( ! function_exists( 'newsai_large_site_mode_skips_radar' ) ) {
	function newsai_large_site_mode_skips_radar() {
		return newsai_large_site_mode_enabled();
	}
}

if ( ! function_exists( 'newsai_large_site_mode_skips_tag_guard' ) ) {
	function newsai_large_site_mode_skips_tag_guard() {
		return newsai_large_site_mode_enabled();
	}
}

if ( ! function_exists( 'newsai_should_skip_auto_timeline_inject' ) ) {
	/**
	 * Skip Auto-Timeline the_content injection (shortcode / Manual still work).
	 *
	 * Only explicit performance switches block Auto. Post-count auto-detect alone must NOT
	 * kill storytelling — megasites still want Auto when Manual proves matches exist; the
	 * 7-day post-meta timeline cache keeps the frontend cheap.
	 *
	 * @return bool
	 */
	function newsai_should_skip_auto_timeline_inject() {
		if ( function_exists( 'newsai_lite_mode_skips_frontend_injections' ) && newsai_lite_mode_skips_frontend_injections() ) {
			return true;
		}
		// Explicit checkbox only — not newsai_is_large_site() (auto ≥5000 posts).
		if ( function_exists( 'newsai_large_site_mode_enabled' ) && newsai_large_site_mode_enabled() ) {
			return true;
		}
		return false;
	}
}

if ( ! function_exists( 'newsai_timeline_meta_html_key' ) ) {
	function newsai_timeline_meta_html_key() {
		return '_nros_timeline_html_v6';
	}
}

if ( ! function_exists( 'newsai_timeline_meta_time_key' ) ) {
	function newsai_timeline_meta_time_key() {
		return '_nros_timeline_html_v6_ts';
	}
}

if ( ! function_exists( 'newsai_timeline_cache_ttl' ) ) {
	function newsai_timeline_cache_ttl() {
		return (int) apply_filters( 'newsai_timeline_cache_ttl', 7 * DAY_IN_SECONDS );
	}
}

if ( ! function_exists( 'newsai_timeline_html_is_valid' ) ) {
	/**
	 * True only when HTML has at least one real timeline/link item (not an empty shell).
	 *
	 * @param string $html Cached or generated fragment.
	 * @return bool
	 */
	function newsai_timeline_html_is_valid( $html ) {
		$html = (string) $html;
		if ( $html === '' || strpos( $html, 'newsai-story-cluster' ) === false ) {
			return false;
		}
		// Must contain at least one rendered item (timeline li or links list li).
		return (bool) preg_match( '/newsai-story-cluster__(?:item|list)/', $html );
	}
}

if ( ! function_exists( 'newsai_timeline_get_cached_html' ) ) {
	/**
	 * Read timeline HTML from post meta (7d) with transient fallback.
	 *
	 * @param int $post_id Post ID.
	 * @return string Empty when miss/expired/invalid shell.
	 */
	function newsai_timeline_get_cached_html( $post_id ) {
		$post_id = (int) $post_id;
		if ( $post_id < 1 ) {
			return '';
		}
		$html = (string) get_post_meta( $post_id, newsai_timeline_meta_html_key(), true );
		$ts   = (int) get_post_meta( $post_id, newsai_timeline_meta_time_key(), true );
		if ( $html !== '' && $ts > 0 && ( time() - $ts ) < newsai_timeline_cache_ttl() ) {
			if ( newsai_timeline_html_is_valid( $html ) ) {
				return $html;
			}
			// Stale empty shell — drop it so Auto regenerates like Manual.
			newsai_timeline_clear_cached_html( $post_id );
			return '';
		}
		$transient = get_transient( 'nros_timeline_html_v6_' . $post_id );
		if ( false !== $transient && is_string( $transient ) ) {
			if ( newsai_timeline_html_is_valid( $transient ) ) {
				return $transient;
			}
			delete_transient( 'nros_timeline_html_v6_' . $post_id );
		}
		// Drop legacy v5 empties that caused Auto=empty while Manual worked.
		$legacy = get_transient( 'nros_timeline_html_v5_' . $post_id );
		if ( false !== $legacy ) {
			delete_transient( 'nros_timeline_html_v5_' . $post_id );
		}
		delete_post_meta( $post_id, '_nros_timeline_html_v5' );
		delete_post_meta( $post_id, '_nros_timeline_html_v5_ts' );
		return '';
	}
}

if ( ! function_exists( 'newsai_timeline_set_cached_html' ) ) {
	/**
	 * Persist timeline HTML to post meta + short transient.
	 *
	 * @param int    $post_id Post ID.
	 * @param string $html    HTML fragment.
	 */
	function newsai_timeline_set_cached_html( $post_id, $html ) {
		$post_id = (int) $post_id;
		$html    = (string) $html;
		if ( $post_id < 1 || ! newsai_timeline_html_is_valid( $html ) ) {
			return;
		}
		update_post_meta( $post_id, newsai_timeline_meta_html_key(), $html );
		update_post_meta( $post_id, newsai_timeline_meta_time_key(), time() );
		set_transient( 'nros_timeline_html_v6_' . $post_id, $html, 12 * HOUR_IN_SECONDS );
	}
}

if ( ! function_exists( 'newsai_timeline_clear_cached_html' ) ) {
	/**
	 * @param int $post_id Post ID.
	 */
	function newsai_timeline_clear_cached_html( $post_id ) {
		$post_id = (int) $post_id;
		if ( $post_id < 1 ) {
			return;
		}
		delete_post_meta( $post_id, newsai_timeline_meta_html_key() );
		delete_post_meta( $post_id, newsai_timeline_meta_time_key() );
		delete_transient( 'nros_timeline_html_v6_' . $post_id );
		delete_transient( 'nros_timeline_html_v5_' . $post_id );
		delete_post_meta( $post_id, '_nros_timeline_html_v5' );
		delete_post_meta( $post_id, '_nros_timeline_html_v5_ts' );
	}
}

if ( ! function_exists( 'newsai_activation_defer_heavy_crons' ) ) {
	function newsai_activation_defer_heavy_crons() {
		return (bool) apply_filters( 'newsai_activation_defer_heavy_crons', true );
	}
}

if ( ! function_exists( 'newsai_schedule_heavy_crons_staggered' ) ) {
	/**
	 * Schedule background jobs with staggered first-run times (avoids WP-Cron stampede).
	 *
	 * @param int $base_offset Seconds from now for the first job.
	 */
	function newsai_schedule_heavy_crons_staggered( $base_offset = 0 ) {
		$base = time() + max( 0, (int) $base_offset );
		$big  = function_exists( 'newsai_is_large_site' ) && newsai_is_large_site();

		if ( function_exists( 'nros_discover_score_schedule_cron' ) ) {
			wp_clear_scheduled_hook( 'nros_refresh_trend_keyword_cache' );
			if ( ! wp_next_scheduled( 'nros_refresh_trend_keyword_cache' ) ) {
				wp_schedule_event( $base + HOUR_IN_SECONDS, 'daily', 'nros_refresh_trend_keyword_cache' );
			}
		}

		if ( function_exists( 'newsai_schedule_weekly_cleanup' ) ) {
			wp_clear_scheduled_hook( 'newsai_weekly_cleanup' );
			if ( ! wp_next_scheduled( 'newsai_weekly_cleanup' ) ) {
				wp_schedule_event( $base + 6 * HOUR_IN_SECONDS, 'weekly', 'newsai_weekly_cleanup' );
			}
		}

		if ( function_exists( 'newsai_schedule_seasonal_radar' ) ) {
			wp_clear_scheduled_hook( 'newsai_seasonal_radar_refresh' );
			if ( function_exists( 'newsai_seasonal_radar_enabled' ) && newsai_seasonal_radar_enabled() ) {
				if ( ! wp_next_scheduled( 'newsai_seasonal_radar_refresh' ) ) {
					wp_schedule_event( $base + 4 * HOUR_IN_SECONDS, 'weekly', 'newsai_seasonal_radar_refresh' );
				}
			}
		}

		if ( function_exists( 'newsai_gsc_unschedule_cron' ) && function_exists( 'newsai_gsc_should_schedule_cron' ) ) {
			newsai_gsc_unschedule_cron();
			if ( newsai_gsc_should_schedule_cron() ) {
				$gsc_first = $base + ( $big ? 12 * HOUR_IN_SECONDS : 6 * HOUR_IN_SECONDS );
				wp_schedule_event( $gsc_first, 'daily', 'newsai_gsc_daily_sync' );
			}
		}

		if ( function_exists( 'nros_schema_schedule_legacy_warm_cron' ) ) {
			$warm_delay = $big ? 15 * MINUTE_IN_SECONDS : 5 * MINUTE_IN_SECONDS;
			add_filter(
				'nros_schema_warm_cron_first_offset',
				static function () use ( $warm_delay ) {
					return $warm_delay;
				}
			);
			nros_schema_schedule_legacy_warm_cron( true );
			remove_all_filters( 'nros_schema_warm_cron_first_offset' );
		}

		update_option( 'newsai_deferred_activation_done', time(), false );
	}
}

if ( ! function_exists( 'newsai_schedule_activation_crons' ) ) {
	/**
	 * Activation / upgrade cron bootstrap — light jobs now, heavy jobs staggered.
	 */
	function newsai_schedule_activation_crons() {
		if ( function_exists( 'newsai_breaking_schedule_cron' ) ) {
			newsai_breaking_schedule_cron();
		}
		if ( function_exists( 'newsai_pro_schedule_license_cron' ) ) {
			newsai_pro_schedule_license_cron();
		}
		if ( function_exists( 'newsai_task_schedule_purge_cron' ) ) {
			newsai_task_schedule_purge_cron();
		}
		if ( function_exists( 'newsai_indexnow_flush_rewrite_rules' ) ) {
			newsai_indexnow_flush_rewrite_rules();
		}

		if ( ! newsai_activation_defer_heavy_crons() ) {
			newsai_schedule_heavy_crons_staggered( 60 );
			return;
		}

		if ( ! wp_next_scheduled( 'newsai_deferred_activation_init' ) ) {
			$delay = newsai_is_large_site() ? 10 * MINUTE_IN_SECONDS : 3 * MINUTE_IN_SECONDS;
			wp_schedule_single_event( time() + $delay, 'newsai_deferred_activation_init' );
		}
	}
}

add_action(
	'newsai_deferred_activation_init',
	static function () {
		newsai_schedule_heavy_crons_staggered( 90 );
	}
);

if ( ! function_exists( 'newsai_radar_fetch_lock_key' ) ) {
	/**
	 * @param string $kind trends|news.
	 * @param string $geo  Geo code.
	 * @return string
	 */
	function newsai_radar_fetch_lock_key( $kind, $geo ) {
		return 'nros_radar_lock_' . sanitize_key( (string) $kind ) . '_' . strtoupper( sanitize_key( (string) $geo ) );
	}
}

if ( ! function_exists( 'newsai_radar_try_fetch_lock' ) ) {
	/**
	 * Prevent parallel cold rebuilds of the same radar feed.
	 *
	 * @param string $kind trends|news.
	 * @param string $geo  Geo code.
	 * @return bool True when lock acquired.
	 */
	function newsai_radar_try_fetch_lock( $kind, $geo ) {
		$key = newsai_radar_fetch_lock_key( $kind, $geo );
		if ( get_transient( $key ) ) {
			return false;
		}
		set_transient( $key, 1, 90 );
		return true;
	}
}

if ( ! function_exists( 'newsai_radar_release_fetch_lock' ) ) {
	function newsai_radar_release_fetch_lock( $kind, $geo ) {
		delete_transient( newsai_radar_fetch_lock_key( $kind, $geo ) );
	}
}

add_filter(
	'nros_schema_warm_batch_size',
	static function ( $size ) {
		$size = (int) $size;
		$done = (int) get_option( 'newsai_deferred_activation_done', 0 );
		if ( $done > 0 && ( time() - $done ) < DAY_IN_SECONDS ) {
			$size = min( $size, function_exists( 'newsai_is_large_site' ) && newsai_is_large_site() ? 10 : 15 );
		} elseif ( function_exists( 'newsai_is_large_site' ) && newsai_is_large_site() ) {
			$size = min( $size, 20 );
		}
		return $size;
	},
	20
);

add_filter(
	'nros_schema_warm_kick_delay',
	static function ( $seconds ) {
		if ( function_exists( 'newsai_is_large_site' ) && newsai_is_large_site() ) {
			return max( (int) $seconds, 5 * MINUTE_IN_SECONDS );
		}
		return (int) $seconds;
	}
);
