<?php
/**
 * Seasonal Radar — YoY tag/GSC opportunities + trend history (Pro).
 *
 * @package Newsroom_AI_Assistant
 */

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

if ( ! function_exists( 'newsai_seasonal_radar_enabled' ) ) {
	function newsai_seasonal_radar_enabled() {
		if ( ! function_exists( 'newsai_is_pro' ) || ! newsai_is_pro() ) {
			return false;
		}
		return get_option( 'newsai_seasonal_radar_enabled', 'yes' ) === 'yes';
	}
}

if ( ! function_exists( 'newsai_seasonal_lead_days' ) ) {
	function newsai_seasonal_lead_days() {
		$days = (int) get_option( 'newsai_seasonal_lead_days', 30 );
		if ( ! in_array( $days, [ 14, 30, 45 ], true ) ) {
			$days = 30;
		}
		return $days;
	}
}

if ( ! function_exists( 'newsai_seasonal_min_clicks' ) ) {
	function newsai_seasonal_min_clicks() {
		$min = (int) get_option( 'newsai_seasonal_min_clicks', 25 );
		return max( 5, min( 5000, $min ) );
	}
}

if ( ! function_exists( 'newsai_seasonal_email_enabled' ) ) {
	function newsai_seasonal_email_enabled() {
		return get_option( 'newsai_seasonal_email_enabled', 'yes' ) === 'yes';
	}
}

if ( ! function_exists( 'newsai_trend_history_option_key' ) ) {
	function newsai_trend_history_option_key() {
		return 'newsai_trend_history';
	}
}

if ( ! function_exists( 'newsai_trend_history_append_from_cache' ) ) {
	/**
	 * Append today's trend tokens to rolling history (called after daily trend refresh).
	 */
	function newsai_trend_history_append_from_cache() {
		$cache_key = function_exists( 'nros_discover_score_option_key' ) ? nros_discover_score_option_key() : 'nros_trend_keyword_cache';
		$cache     = get_option( $cache_key, [] );
		if ( ! is_array( $cache ) || empty( $cache['tokens'] ) || ! is_array( $cache['tokens'] ) ) {
			return;
		}
		$day = gmdate( 'Y-m-d' );
		$hist = get_option( newsai_trend_history_option_key(), [] );
		if ( ! is_array( $hist ) ) {
			$hist = [];
		}
		if ( ! isset( $hist['days'] ) || ! is_array( $hist['days'] ) ) {
			$hist['days'] = [];
		}
		$tokens = array_values( array_unique( array_filter( array_map( 'sanitize_text_field', $cache['tokens'] ) ) ) );
		if ( count( $tokens ) > 40 ) {
			$tokens = array_slice( $tokens, 0, 40 );
		}
		$hist['days'][ $day ] = $tokens;
		ksort( $hist['days'] );
		if ( count( $hist['days'] ) > 400 ) {
			$hist['days'] = array_slice( $hist['days'], -400, null, true );
		}
		$hist['updated'] = time();
		update_option( newsai_trend_history_option_key(), $hist, false );
	}
}
add_action( 'nros_refresh_trend_keyword_cache', 'newsai_trend_history_append_from_cache', 20 );

if ( ! function_exists( 'newsai_seasonal_normalize_term' ) ) {
	function newsai_seasonal_normalize_term( $text ) {
		$text = remove_accents( wp_strip_all_tags( (string) $text ) );
		$text = mb_strtolower( $text, 'UTF-8' );
		return trim( preg_replace( '/\s+/u', ' ', $text ) );
	}
}

if ( ! function_exists( 'newsai_seasonal_term_matches_trends' ) ) {
	/**
	 * @param string   $term_name Tag/keyword label.
	 * @param string[] $tokens    Trend tokens.
	 */
	function newsai_seasonal_term_matches_trends( $term_name, array $tokens ) {
		$norm = newsai_seasonal_normalize_term( $term_name );
		if ( $norm === '' ) {
			return false;
		}
		foreach ( $tokens as $token ) {
			$t = newsai_seasonal_normalize_term( $token );
			if ( $t === '' ) {
				continue;
			}
			if ( $norm === $t || strpos( $norm, $t ) !== false || strpos( $t, $norm ) !== false ) {
				return true;
			}
		}
		return false;
	}
}

if ( ! function_exists( 'newsai_seasonal_current_trend_tokens' ) ) {
	/**
	 * @return string[]
	 */
	function newsai_seasonal_current_trend_tokens() {
		$cache_key = function_exists( 'nros_discover_score_option_key' ) ? nros_discover_score_option_key() : 'nros_trend_keyword_cache';
		$cache     = get_option( $cache_key, [] );
		if ( is_array( $cache ) && ! empty( $cache['tokens'] ) && is_array( $cache['tokens'] ) ) {
			return array_values( $cache['tokens'] );
		}
		return [];
	}
}

if ( ! function_exists( 'newsai_seasonal_history_tokens_near_date' ) ) {
	/**
	 * Trend tokens recorded around the same calendar window last year (±7 days).
	 *
	 * @return string[]
	 */
	function newsai_seasonal_history_tokens_near_date( $anchor_ymd ) {
		$hist = get_option( newsai_trend_history_option_key(), [] );
		if ( ! is_array( $hist ) || empty( $hist['days'] ) || ! is_array( $hist['days'] ) ) {
			return [];
		}
		$anchor_ts = strtotime( $anchor_ymd . ' UTC' );
		if ( $anchor_ts === false ) {
			return [];
		}
		$out = [];
		for ( $offset = -7; $offset <= 7; $offset++ ) {
			$key = gmdate( 'Y-m-d', $anchor_ts + ( $offset * DAY_IN_SECONDS ) );
			if ( ! empty( $hist['days'][ $key ] ) && is_array( $hist['days'][ $key ] ) ) {
				$out = array_merge( $out, $hist['days'][ $key ] );
			}
		}
		return array_values( array_unique( array_filter( $out ) ) );
	}
}

if ( ! function_exists( 'newsai_seasonal_build_radar_item' ) ) {
	/**
	 * @param string $source gsc_query|tag
	 */
	function newsai_seasonal_build_radar_item( $name, $clicks, $impr, $source, $yoy_start, $yoy_end, $target_start_ts, $target_end_ts, $lead, array $current_tokens, array $history_tokens ) {
		$trend_now  = newsai_seasonal_term_matches_trends( $name, $current_tokens );
		$hist_match = newsai_seasonal_term_matches_trends( $name, $history_tokens );
		$score      = (int) $clicks;
		if ( $source === 'gsc_query' ) {
			$score += (int) round( $clicks * 0.1 );
		}
		if ( $trend_now ) {
			$score += (int) round( $clicks * 0.25 );
		}
		if ( $hist_match ) {
			$score += (int) round( $clicks * 0.15 );
		}
		$hint = ( $source === 'gsc_query' )
			? sprintf(
				/* translators: 1: search query, 2: click count, 3: date window, 4: lead days */
				__( 'Last year around this season the query “%1$s” drove %2$s GSC clicks (%3$s). Plan coverage ~%4$d days ahead.', 'newsroom-ai-assistant' ),
				$name,
				number_format_i18n( $clicks ),
				$yoy_start . '–' . $yoy_end,
				$lead
			)
			: sprintf(
				/* translators: 1: tag name, 2: year-ago click count, 3: calendar window, 4: lead days */
				__( 'Last year around this season tag “%1$s” drove %2$s GSC clicks (%3$s). Plan refresh or new angles ~%4$d days ahead.', 'newsroom-ai-assistant' ),
				$name,
				number_format_i18n( $clicks ),
				$yoy_start . '–' . $yoy_end,
				$lead
			);

		return [
			'term'          => $name,
			'source'        => $source,
			'yoy_clicks'    => (int) $clicks,
			'yoy_impr'      => (int) $impr,
			'yoy_window'    => $yoy_start . ' → ' . $yoy_end,
			'target_window' => gmdate( 'M j', $target_start_ts ) . ' – ' . gmdate( 'M j', $target_end_ts ),
			'trend_now'     => $trend_now,
			'trend_history' => $hist_match,
			'score'         => $score,
			'hint'          => $hint,
		];
	}
}

if ( ! function_exists( 'newsai_seasonal_radar_compute' ) ) {
	/**
	 * YoY opportunities from GSC search queries + tagged articles (same calendar window last year).
	 *
	 * @return array{updated:int,lead_days:int,window_start:string,window_end:string,items:list<array<string,mixed>>}
	 */
	function newsai_seasonal_radar_compute() {
		$empty = [
			'updated'      => time(),
			'lead_days'    => newsai_seasonal_lead_days(),
			'window_start' => '',
			'window_end'   => '',
			'items'        => [],
		];
		if ( ! newsai_seasonal_radar_enabled() ) {
			return $empty;
		}
		if ( ! function_exists( 'newsai_gsc_data_available' ) || ! newsai_gsc_data_available() ) {
			return $empty;
		}

		global $wpdb;
		$lead       = newsai_seasonal_lead_days();
		$min_clicks = newsai_seasonal_min_clicks();
		$window_len = 14;

		$target_start_ts = strtotime( '+' . $lead . ' days' );
		$target_end_ts   = $target_start_ts + ( ( $window_len - 1 ) * DAY_IN_SECONDS );
		$yoy_start       = gmdate( 'Y-m-d', strtotime( '-' . 365 . ' days', $target_start_ts ) );
		$yoy_end         = gmdate( 'Y-m-d', strtotime( '-' . 365 . ' days', $target_end_ts ) );

		$gsc_table = newsai_gsc_table_name();
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
		$rows = $wpdb->get_results(
			$wpdb->prepare(
				"SELECT t.term_id, t.name, SUM(g.clicks) AS yoy_clicks, SUM(g.impressions) AS yoy_impr
				FROM {$gsc_table} g
				INNER JOIN {$wpdb->term_relationships} tr ON tr.object_id = g.post_id
				INNER JOIN {$wpdb->term_taxonomy} tt ON tt.term_taxonomy_id = tr.term_taxonomy_id AND tt.taxonomy = 'post_tag'
				INNER JOIN {$wpdb->terms} t ON t.term_id = tt.term_id
				WHERE g.data_date >= %s AND g.data_date <= %s
				GROUP BY t.term_id, t.name
				HAVING yoy_clicks >= %d
				ORDER BY yoy_clicks DESC
				LIMIT 20",
				$yoy_start,
				$yoy_end,
				$min_clicks
			),
			ARRAY_A
		);

		$current_tokens = newsai_seasonal_current_trend_tokens();
		$history_tokens = newsai_seasonal_history_tokens_near_date( gmdate( 'Y-m-d', $target_start_ts ) );
		$by_norm        = [];

		if ( function_exists( 'newsai_seasonal_yoy_gsc_queries' ) ) {
			foreach ( newsai_seasonal_yoy_gsc_queries( $yoy_start, $yoy_end, $min_clicks ) as $qrow ) {
				$name = (string) ( $qrow['query_text'] ?? '' );
				if ( $name === '' ) {
					continue;
				}
				$item = newsai_seasonal_build_radar_item(
					$name,
					(int) ( $qrow['yoy_clicks'] ?? 0 ),
					(int) ( $qrow['yoy_impr'] ?? 0 ),
					'gsc_query',
					$yoy_start,
					$yoy_end,
					$target_start_ts,
					$target_end_ts,
					$lead,
					$current_tokens,
					$history_tokens
				);
				$by_norm[ newsai_seasonal_normalize_term( $name ) ] = $item;
			}
		}

		foreach ( (array) $rows as $row ) {
			$name   = (string) ( $row['name'] ?? '' );
			$clicks = (int) ( $row['yoy_clicks'] ?? 0 );
			if ( $name === '' || $clicks < 1 ) {
				continue;
			}
			$norm = newsai_seasonal_normalize_term( $name );
			$item = newsai_seasonal_build_radar_item(
				$name,
				$clicks,
				(int) ( $row['yoy_impr'] ?? 0 ),
				'tag',
				$yoy_start,
				$yoy_end,
				$target_start_ts,
				$target_end_ts,
				$lead,
				$current_tokens,
				$history_tokens
			);
			if ( ! isset( $by_norm[ $norm ] ) || (int) $item['score'] > (int) ( $by_norm[ $norm ]['score'] ?? 0 ) ) {
				$by_norm[ $norm ] = $item;
			}
		}

		$items = array_values( $by_norm );
		usort(
			$items,
			static function ( $a, $b ) {
				return (int) ( $b['score'] ?? 0 ) <=> (int) ( $a['score'] ?? 0 );
			}
		);
		$items = array_slice( $items, 0, 8 );

		$payload = [
			'updated'      => time(),
			'lead_days'    => $lead,
			'window_start' => gmdate( 'Y-m-d', $target_start_ts ),
			'window_end'   => gmdate( 'Y-m-d', $target_end_ts ),
			'yoy_start'    => $yoy_start,
			'yoy_end'      => $yoy_end,
			'items'        => $items,
		];
		update_option( 'newsai_seasonal_radar_cache', $payload, false );
		return $payload;
	}
}

if ( ! function_exists( 'newsai_seasonal_radar_get_cached' ) ) {
	function newsai_seasonal_radar_get_cached() {
		$cached = get_option( 'newsai_seasonal_radar_cache', [] );
		if ( is_array( $cached ) && ! empty( $cached['items'] ) && isset( $cached['updated'] ) ) {
			if ( ( time() - (int) $cached['updated'] ) < 7 * DAY_IN_SECONDS ) {
				return $cached;
			}
		}
		return newsai_seasonal_radar_compute();
	}
}

if ( ! function_exists( 'newsai_seasonal_radar_refresh_cron' ) ) {
	function newsai_seasonal_radar_refresh_cron() {
		if ( ! newsai_seasonal_radar_enabled() ) {
			return;
		}
		newsai_seasonal_radar_compute();
	}
}
add_action( 'newsai_seasonal_radar_refresh', 'newsai_seasonal_radar_refresh_cron' );

if ( ! function_exists( 'newsai_schedule_seasonal_radar' ) ) {
	function newsai_schedule_seasonal_radar() {
		if ( ! newsai_seasonal_radar_enabled() ) {
			wp_clear_scheduled_hook( 'newsai_seasonal_radar_refresh' );
			return;
		}
		if ( ! wp_next_scheduled( 'newsai_seasonal_radar_refresh' ) ) {
			wp_schedule_event( time() + 2 * HOUR_IN_SECONDS, 'weekly', 'newsai_seasonal_radar_refresh' );
		}
	}
}
add_action( 'admin_init', 'newsai_schedule_seasonal_radar' );

if ( ! function_exists( 'newsai_seasonal_radar_bootstrap_240' ) ) {
	function newsai_seasonal_radar_bootstrap_240() {
		if ( get_option( 'newsai_240_bootstrapped', 'no' ) === 'yes' ) {
			return;
		}
		if ( function_exists( 'newsai_trend_history_append_from_cache' ) ) {
			newsai_trend_history_append_from_cache();
		}
		if ( function_exists( 'newsai_seasonal_radar_compute' ) && newsai_seasonal_radar_enabled() ) {
			newsai_seasonal_radar_compute();
		}
		update_option( 'newsai_240_bootstrapped', 'yes', false );
	}
}
add_action( 'admin_init', 'newsai_seasonal_radar_bootstrap_240', 5 );

if ( ! function_exists( 'newsai_seasonal_radar_render_panel' ) ) {
	/**
	 * Chief Insights — seasonal opportunities card.
	 */
	function newsai_seasonal_radar_render_panel() {
		if ( ! newsai_seasonal_radar_enabled() ) {
			return;
		}
		$data  = newsai_seasonal_radar_get_cached();
		$items = isset( $data['items'] ) && is_array( $data['items'] ) ? $data['items'] : [];
		$lead  = (int) ( $data['lead_days'] ?? newsai_seasonal_lead_days() );
		?>
		<div class="nros-card nros-col-12" style="margin-bottom:16px;">
			<h3><?php echo esc_html__( 'Seasonal radar — next opportunities', 'newsroom-ai-assistant' ); ?></h3>
			<p class="nros-insights-table-hint">
				<?php
				echo esc_html(
					sprintf(
						/* translators: 1: lead days, 2: UTC date */
						__( 'YoY GSC keywords & tags · ~%1$d-day lead · updated %2$s', 'newsroom-ai-assistant' ),
						$lead,
						isset( $data['updated'] ) ? wp_date( 'M j, H:i', (int) $data['updated'] ) : '—'
					)
				);
				?>
			</p>
			<?php if ( empty( $items ) ) : ?>
				<p class="description"><?php echo esc_html__( 'No seasonal signals yet — run GSC sync (stores search queries) and publish tagged articles for a few weeks.', 'newsroom-ai-assistant' ); ?></p>
			<?php else : ?>
				<table class="widefat striped nros-insights-table">
					<thead>
						<tr>
							<th><?php echo esc_html__( 'Keyword / tag', 'newsroom-ai-assistant' ); ?></th>
							<th><?php echo esc_html__( 'Source', 'newsroom-ai-assistant' ); ?></th>
							<th><?php echo esc_html__( 'YoY clicks', 'newsroom-ai-assistant' ); ?></th>
							<th><?php echo esc_html__( 'Target window', 'newsroom-ai-assistant' ); ?></th>
							<th><?php echo esc_html__( 'Signals', 'newsroom-ai-assistant' ); ?></th>
						</tr>
					</thead>
					<tbody>
					<?php foreach ( $items as $item ) : ?>
						<tr>
							<td><strong><?php echo esc_html( (string) ( $item['term'] ?? '' ) ); ?></strong>
								<div class="description" style="margin-top:4px;"><?php echo esc_html( (string) ( $item['hint'] ?? '' ) ); ?></div>
							</td>
							<td><?php echo ( ( $item['source'] ?? '' ) === 'gsc_query' ) ? esc_html__( 'GSC query', 'newsroom-ai-assistant' ) : esc_html__( 'Tag', 'newsroom-ai-assistant' ); ?></td>
							<td><?php echo esc_html( number_format_i18n( (int) ( $item['yoy_clicks'] ?? 0 ) ) ); ?></td>
							<td><?php echo esc_html( (string) ( $item['target_window'] ?? '' ) ); ?></td>
							<td>
								<?php if ( ! empty( $item['trend_now'] ) ) : ?><span class="nros-chief-live-badge" style="margin-right:4px;"><?php echo esc_html__( 'Trending now', 'newsroom-ai-assistant' ); ?></span><?php endif; ?>
								<?php if ( ! empty( $item['trend_history'] ) ) : ?><span class="nros-chief-live-badge" style="background:#fef3c7;color:#92400e;"><?php echo esc_html__( 'Seasonal history', 'newsroom-ai-assistant' ); ?></span><?php endif; ?>
							</td>
						</tr>
					<?php endforeach; ?>
					</tbody>
				</table>
			<?php endif; ?>
		</div>
		<?php
	}
}

if ( ! function_exists( 'newsai_weekly_report_seasonal_section' ) ) {
	/**
	 * @return array{enabled:bool,items:list<array<string,mixed>>}
	 */
	function newsai_weekly_report_seasonal_section() {
		if ( ! newsai_seasonal_radar_enabled() || ! newsai_seasonal_email_enabled() ) {
			return [ 'enabled' => false, 'items' => [] ];
		}
		$data  = newsai_seasonal_radar_get_cached();
		$items = isset( $data['items'] ) && is_array( $data['items'] ) ? array_slice( $data['items'], 0, 5 ) : [];
		return [
			'enabled' => ! empty( $items ),
			'items'   => $items,
			'lead'    => (int) ( $data['lead_days'] ?? 30 ),
		];
	}
}
