<?php
/**
 * AI Security Advisor – scheduled full-report generation (Pro).
 *
 * @package Security_Ninja
 */

namespace WPSecurityNinja\Plugin\AiAdvisor;

use function WPSecurityNinja\Plugin\secnin_fs;

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

define( 'WF_SN_AI_ADVISOR_CRON', 'wf_sn_ai_advisor_cron' );
define( 'WF_SN_AI_ADVISOR_RUN_SCHEDULED', 'wf_sn_ai_advisor_run_scheduled_report' );

if ( ! class_exists( 'ActionScheduler_Versions' ) ) {
	$action_scheduler_file = null;
	if ( defined( 'WF_SN_PLUGIN_DIR' ) ) {
		$path = WF_SN_PLUGIN_DIR . 'vendor/woocommerce/action-scheduler/action-scheduler.php';
		if ( file_exists( $path ) && is_readable( $path ) ) {
			$action_scheduler_file = $path;
		}
	}
	if ( ! $action_scheduler_file ) {
		$plugin_root = dirname( __DIR__, 2 );
		$path        = $plugin_root . '/vendor/woocommerce/action-scheduler/action-scheduler.php';
		if ( file_exists( $path ) && is_readable( $path ) ) {
			$action_scheduler_file = $path;
		}
	}
	if ( $action_scheduler_file ) {
		require_once $action_scheduler_file;
	}
}

/**
 * Schedules and runs automatic AI full reports for Pro sites.
 */
class Wf_Sn_Ai_Advisor_Scheduler {

	const LOCK_TRANSIENT      = 'wf_sn_ai_advisor_scheduled_running';
	const RESCHEDULE_TRANSIENT = 'wf_sn_ai_advisor_reschedule_check';

	/**
	 * Bootstrap hooks.
	 *
	 * @return void
	 */
	public static function init() {
		add_action( 'init', array( __CLASS__, 'maybe_reschedule' ), 20 );
		add_action( WF_SN_AI_ADVISOR_CRON, array( __CLASS__, 'do_scheduled_report' ) );
		add_action( WF_SN_AI_ADVISOR_RUN_SCHEDULED, array( __CLASS__, 'do_scheduled_report' ) );
		add_action( 'wp_ajax_' . Wf_Sn_Ai_Advisor::AJAX_ACTION_PREFIX . 'run_scheduled_now', array( __CLASS__, 'ajax_run_scheduled_now' ) );
	}

	/**
	 * Whether scheduled AI reports are enabled in settings.
	 *
	 * @return bool
	 */
	public static function is_scheduling_enabled() {
		$options = get_option( 'wf_sn_ai_advisor', array() );
		if ( ! is_array( $options ) ) {
			$options = array();
		}
		return ! empty( $options['scheduled_report_enabled'] );
	}

	/**
	 * Get configured interval slug.
	 *
	 * @return string
	 */
	public static function get_schedule_interval() {
		$options  = get_option( 'wf_sn_ai_advisor', array() );
		if ( ! is_array( $options ) ) {
			$options = array();
		}
		$interval = isset( $options['scheduled_report_interval'] ) ? sanitize_key( (string) $options['scheduled_report_interval'] ) : 'daily';
		$schedules = wp_get_schedules();
		if ( ! isset( $schedules[ $interval ] ) ) {
			$interval = 'daily';
		}
		return $interval;
	}

	/**
	 * Next scheduled run timestamp and backend label.
	 *
	 * @return array{timestamp:int,backend:string}
	 */
	public static function get_scheduler_state() {
		$state = array(
			'timestamp' => 0,
			'backend'   => 'none',
		);

		if ( self::ensure_action_scheduler_loaded() && function_exists( 'as_next_scheduled_action' ) ) {
			$as_timestamp = as_next_scheduled_action( WF_SN_AI_ADVISOR_RUN_SCHEDULED, array(), 'security-ninja' );
			if ( false !== $as_timestamp && 0 < (int) $as_timestamp ) {
				$state['timestamp'] = (int) $as_timestamp;
				$state['backend']   = 'action_scheduler';
				return $state;
			}
		}

		$wp_timestamp = wp_next_scheduled( WF_SN_AI_ADVISOR_CRON );
		if ( false !== $wp_timestamp && 0 < (int) $wp_timestamp ) {
			$state['timestamp'] = (int) $wp_timestamp;
			$state['backend']   = 'wp_cron';
		}

		return $state;
	}

	/**
	 * Self-heal missing schedule when enabled.
	 *
	 * @return void
	 */
	public static function maybe_reschedule() {
		$can_use_premium = false;
		if ( secnin_fs()->can_use_premium_code__premium_only() ) {
			$can_use_premium = true;
		}
		if ( ! $can_use_premium ) {
			self::clear_all_scheduled_events();
			return;
		}

		if ( ! self::is_scheduling_enabled() ) {
			return;
		}

		if ( get_transient( self::RESCHEDULE_TRANSIENT ) ) {
			return;
		}
		set_transient( self::RESCHEDULE_TRANSIENT, 1, HOUR_IN_SECONDS );

		$state = self::get_scheduler_state();
		if ( 0 < (int) $state['timestamp'] ) {
			return;
		}

		self::setup_cron();

		if ( class_exists( 'WPSecurityNinja\\Plugin\\wf_sn_el_modules' ) ) {
			\WPSecurityNinja\Plugin\wf_sn_el_modules::log_event(
				'security_ninja',
				'ai_advisor',
				__( 'Scheduled AI report event was missing and has been recreated automatically.', 'security-ninja' ),
				''
			);
		}
	}

	/**
	 * Register or clear cron / Action Scheduler events.
	 *
	 * @return void
	 */
	public static function setup_cron() {
		$can_use_premium = false;
		if ( secnin_fs()->can_use_premium_code__premium_only() ) {
			$can_use_premium = true;
		}
		if ( ! $can_use_premium || ! self::is_scheduling_enabled() ) {
			self::clear_all_scheduled_events();
			return;
		}

		$schedule  = self::get_schedule_interval();
		$schedules = wp_get_schedules();
		if ( ! isset( $schedules[ $schedule ]['interval'] ) ) {
			$schedule = 'daily';
		}
		$interval = isset( $schedules[ $schedule ]['interval'] ) ? (int) $schedules[ $schedule ]['interval'] : DAY_IN_SECONDS;

		$has_action_scheduler = self::ensure_action_scheduler_loaded()
			&& function_exists( 'as_schedule_recurring_action' )
			&& function_exists( 'as_unschedule_all_actions' );

		if ( $has_action_scheduler ) {
			wp_clear_scheduled_hook( WF_SN_AI_ADVISOR_CRON );
			as_unschedule_all_actions( WF_SN_AI_ADVISOR_RUN_SCHEDULED, array(), 'security-ninja' );
			as_schedule_recurring_action( time(), $interval, WF_SN_AI_ADVISOR_RUN_SCHEDULED, array(), 'security-ninja' );
			return;
		}

		wp_clear_scheduled_hook( WF_SN_AI_ADVISOR_CRON );
		wp_schedule_event( time(), $schedule, WF_SN_AI_ADVISOR_CRON );
	}

	/**
	 * Run scheduled full report.
	 *
	 * @return void
	 */
	public static function do_scheduled_report() {
		$can_use_premium = false;
		if ( secnin_fs()->can_use_premium_code__premium_only() ) {
			$can_use_premium = true;
		}
		if ( ! $can_use_premium || ! self::is_scheduling_enabled() ) {
			return;
		}

		if ( get_transient( self::LOCK_TRANSIENT ) ) {
			return;
		}
		set_transient( self::LOCK_TRANSIENT, 1, 15 * MINUTE_IN_SECONDS );

		Wf_Sn_Ai_Advisor::load_dependencies();

		$configured = Wf_Sn_Ai_Advisor_Provider_Wp_Connectors::get_configured_providers();
		if ( empty( $configured ) ) {
			self::log_skip_event( __( 'Scheduled AI report skipped: no connector configured.', 'security-ninja' ) );
			delete_transient( self::LOCK_TRANSIENT );
			return;
		}

		if ( function_exists( 'wp_supports_ai' ) && ! wp_supports_ai() ) {
			self::log_skip_event( __( 'Scheduled AI report skipped: WordPress AI is not available on this site.', 'security-ninja' ) );
			delete_transient( self::LOCK_TRANSIENT );
			return;
		}

		$options      = Wf_Sn_Ai_Advisor_Page::get_options();
		$connector_id = isset( $options['last_connector_provider'] ) ? sanitize_key( (string) $options['last_connector_provider'] ) : '';
		$result       = Wf_Sn_Ai_Advisor::run_full_report(
			array(
				'connector_id' => $connector_id,
				'ui_locale'    => get_locale(),
				'source'       => 'scheduled',
			)
		);

		if ( empty( $result['ok'] ) ) {
			$error = isset( $result['error'] ) ? (string) $result['error'] : __( 'Scheduled AI report failed.', 'security-ninja' );
			self::log_skip_event( $error );
		} elseif ( class_exists( 'WPSecurityNinja\\Plugin\\wf_sn_el_modules' ) ) {
			\WPSecurityNinja\Plugin\wf_sn_el_modules::log_event(
				'security_ninja',
				'ai_advisor',
				__( 'Scheduled AI security report generated successfully.', 'security-ninja' ),
				''
			);
		}

		delete_transient( self::LOCK_TRANSIENT );
	}

	/**
	 * Queue or run a scheduled report immediately (Pro admin test).
	 *
	 * @return void
	 */
	public static function ajax_run_scheduled_now() {
		check_ajax_referer( 'wf_sn_ai_advisor', 'nonce' );

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => __( 'Forbidden.', 'security-ninja' ) ) );
		}

		$can_use_premium = false;
		if ( secnin_fs()->can_use_premium_code__premium_only() ) {
			$can_use_premium = true;
		}
		if ( ! $can_use_premium ) {
			wp_send_json_error( array( 'message' => __( 'Premium license required.', 'security-ninja' ) ) );
		}

		if ( self::ensure_action_scheduler_loaded() && function_exists( 'as_schedule_single_action' ) ) {
			$action_id = as_schedule_single_action( time(), WF_SN_AI_ADVISOR_RUN_SCHEDULED, array(), 'security-ninja' );
			if ( $action_id ) {
				self::maybe_run_queue();
				wp_send_json_success(
					array(
						'message' => __( 'AI report queued. It will appear on this page when generation finishes.', 'security-ninja' ),
					)
				);
			}
		}

		self::do_scheduled_report();
		wp_send_json_success(
			array(
				'message' => __( 'AI report generation completed.', 'security-ninja' ),
			)
		);
	}

	/**
	 * Clear all scheduled events for this feature.
	 *
	 * @return void
	 */
	private static function clear_all_scheduled_events() {
		wp_clear_scheduled_hook( WF_SN_AI_ADVISOR_CRON );
		if ( self::ensure_action_scheduler_loaded() && function_exists( 'as_unschedule_all_actions' ) ) {
			as_unschedule_all_actions( WF_SN_AI_ADVISOR_RUN_SCHEDULED, array(), 'security-ninja' );
		}
	}

	/**
	 * Ensure Action Scheduler is loaded.
	 *
	 * @return bool
	 */
	private static function ensure_action_scheduler_loaded() {
		if ( function_exists( 'as_schedule_single_action' ) && function_exists( 'as_has_scheduled_action' ) ) {
			return true;
		}
		$path = null;
		if ( defined( 'WF_SN_PLUGIN_DIR' ) ) {
			$p = WF_SN_PLUGIN_DIR . 'vendor/woocommerce/action-scheduler/action-scheduler.php';
			if ( file_exists( $p ) && is_readable( $p ) ) {
				$path = $p;
			}
		}
		if ( ! $path ) {
			$plugin_root = dirname( __DIR__, 2 );
			$p           = $plugin_root . '/vendor/woocommerce/action-scheduler/action-scheduler.php';
			if ( file_exists( $p ) && is_readable( $p ) ) {
				$path = $p;
			}
		}
		if ( $path ) {
			require_once $path;
			return function_exists( 'as_schedule_single_action' );
		}
		return false;
	}

	/**
	 * Trigger Action Scheduler queue runner if needed.
	 *
	 * @return void
	 */
	private static function maybe_run_queue() {
		if ( self::ensure_action_scheduler_loaded() && function_exists( 'as_has_scheduled_action' ) && function_exists( 'as_enqueue_async_action' ) ) {
			if ( ! as_has_scheduled_action( 'action_scheduler_run_queue' ) ) {
				as_enqueue_async_action( 'action_scheduler_run_queue', array(), 'action-scheduler' );
			}
		}
	}

	/**
	 * Log a skipped or failed scheduled run.
	 *
	 * @param string $message Message.
	 * @return void
	 */
	private static function log_skip_event( $message ) {
		if ( class_exists( 'WPSecurityNinja\\Plugin\\wf_sn_el_modules' ) ) {
			\WPSecurityNinja\Plugin\wf_sn_el_modules::log_event(
				'security_ninja',
				'ai_advisor',
				$message,
				''
			);
		}
	}
}
