<?php
/**
 * Activity Guard rest route.
 *
 * This class is used to response and all rest route works.
 *
 * @package WPNTS\Inc
 */

namespace WPNTS\Inc;

use WPNTS\Inc\wpnts_nts_fs; // phpcs:ignore
use WPNTS\Inc\Activate; // phpcs:ignore
use WPNTS\Inc\Deactivate; // phpcs:ignore
use WPNTS\Inc\Database\DB; // phpcs:ignore
use WPNTS\Inc\SlackAttachment; // phpcs:ignore
use WPNTS\Inc\SlackChannelRouter; // phpcs:ignore

defined('ABSPATH') || die('Hey, what are you doing here? You silly human!');
/**
 * Websitecron used to rest route created.
 *
 * @since 1.0.0
 */
class Websitecron {

	/**
	 * Construct method.
	 *
	 * @since 1.0.0
	 */
	public function __construct() {
		$wpnts_db_instance = new DB();
		$schedules_int = get_option( 'wpntswebhook_website_downtime_alerts');
		$schedules_interval = json_decode($schedules_int);
		$website_cron_create_notice = $schedules_interval->website_cron_create_notice ?? 'false';
		$website_cron_delete_notice = $schedules_interval->website_cron_delete_notice ?? 'false';

		// Simply check the cron event schedule, logging, and slack notifications.
		if ( true === $website_cron_create_notice ) {
			add_filter( 'schedule_event', [ $this, 'wpnts_cron_event_scheduled' ], 10, 1 );
		}

		// Check if the cron event is deleted, logging, and slack notifications.
		if ( true === $website_cron_delete_notice ) {
			add_action( 'pre_unschedule_event', [ $this, 'wpnts_cron_event_deleted' ], 10, 4 );
		}
	}


	/**
	 * Function to handle cron event scheduling, logging, and Slack notifications.
	 *
	 * @param object $event Event object representing the scheduled cron job.
	 * @return object $event Modified event object.
	 */
	public function wpnts_cron_event_scheduled( $event ) {
		if ( isset( $event->hook ) ) {
			$hook = $event->hook;

			// Define a threshold time (1 minute in seconds).
			$threshold = 1 * MINUTE_IN_SECONDS;

			// Get the last execution timestamp for this cron job.
			$last_execution_time = get_option( 'wpnts_cron_last_execution_' . $hook, 0 );

			// Check if enough time has passed since the last execution.
			if ( ( time() - $last_execution_time ) < $threshold ) {
				// If not enough time has passed, skip logging and return the event.
				return $event;
			}

			// Update the last execution time to current time.
			update_option( 'wpnts_cron_last_execution_' . $hook, time() );

			// Get details about the scheduled event.
			$next_run_time = wp_next_scheduled( $hook );

			// Handle one-time tasks if no next scheduled run time.
			if ( $next_run_time === false ) {
				$next_run_time = current_time( 'timestamp' );
				$interval = 'Once (Single)';
			} else {
				$first_run_time = gmdate( 'F j, Y g:i:s a', $next_run_time );
				$interval = isset( $event->interval ) ? $event->interval : 'N/A';

				// Format the interval.
				if ( $interval === 'N/A' ) {
					$interval = 'Once (Single)';
				} else {
					$interval = $this->format_cron_interval( $interval );
				}
			}

			// Get current user details for logging.
			$current_user = wp_get_current_user();
			$attachmentHandler = new SlackAttachment();
			$site_url = $attachmentHandler->getSiteURLAddOption();

			// Construct the log and Slack message.
			$log_message = "A new cron task called <b>'$hook'</b> has been scheduled. \n";
			$log_message .= 'The task is scheduled to run on: ' . gmdate( 'F j, Y g:i:s a', $next_run_time ) . ". \n";
			$log_message .= "Task's interval: " . $interval . ". \n";
			$log_message .= "$site_url";

			$slack_message = "A new cron task called *{$hook}* has been scheduled. \n";
			$slack_message .= 'The task is scheduled to run on: ' . gmdate( 'F j, Y g:i:s a', $next_run_time ) . ". \n";
			$slack_message .= "Task's interval: " . $interval . ". \n";
			$slack_message .= "$site_url";

			// Send notification to Slack.
			$this->wpnts_notify_slack( $slack_message );

			// Log the cron event details into the database.
			$severity = 'Medium';
			$event_type = 'Cron';
			$time = current_time( 'mysql' );
			$sender = 'System';
			$ip = $attachmentHandler->get_user_ip();
			$attachmentHandler->log_activity_to_db( $severity, $time, $ip, $sender, $event_type, $log_message );
		}

		return $event;
	}

	/**
	 * Helper function to format the cron interval into a human-readable string.
	 *
	 * @param int $interval Interval in seconds.
	 * @return string Human-readable interval format.
	 */
	private function format_cron_interval( $interval ) {
		$interval_in_minutes = $interval / 60;
		$interval_in_hours = $interval / 3600;

		if ( $interval_in_hours >= 1 ) {
			return "$interval_in_hours hour" . ( $interval_in_hours > 1 ? 's' : '' );
		} elseif ( $interval_in_minutes >= 1 ) {
			return "$interval_in_minutes minute" . ( $interval_in_minutes > 1 ? 's' : '' );
		} else {
			return "$interval seconds";
		}
	}


	/**
	 * Function to handle the deletion of cron jobs, logging, and Slack notifications.
	 *
	 * @param bool   $pre Whether the event is scheduled or not.
	 * @param int    $timestamp The timestamp when the cron job is scheduled.
	 * @param string $hookname The cron job hook name.
	 * @param array  $args The arguments passed to the cron job.
	 */
	public function wpnts_cron_event_deleted( $pre, $timestamp, $hookname, $args ) {
		// Only proceed if the cron job is unscheduled (pre is false).
		if ( ! $pre && ! defined( 'DOING_CRON' ) ) {
			// Get the last execution time for this cron job (if any).
			$last_execution_time = get_option( 'wpnts_cron_last_execution_' . $hookname, 0 );

			// Construct the log and Slack messages for cron deletion.
			$log_message = "The recurring task called <b>'$hookname'</b> has been deleted. \n";
			$log_message .= 'The task was last scheduled to run at: ' . ( $last_execution_time ? gmdate( 'F j, Y g:i:s a', $last_execution_time ) : 'Not yet executed' ) . ". \n";

			$slack_message = "The recurring task called *{$hookname}* has been deleted. \n";
			$slack_message .= 'The task was last scheduled to run at: ' . ( $last_execution_time ? gmdate( 'F j, Y g:i:s a', $last_execution_time ) : 'Not yet executed' ) . ". \n";

			// Get current user details for logging.
			$attachmentHandler = new SlackAttachment();
			$site_url = $attachmentHandler->getSiteURLAddOption();

			// Add the site URL to the message.
			$log_message .= "$site_url";
			$slack_message .= "$site_url";

			// Send notification to Slack.
			$this->wpnts_notify_slack( $slack_message );

			// Log the cron deletion event to the database.
			$severity = 'Medium';
			$event_type = 'Cron Deletion';
			$time = current_time( 'mysql' );
			$sender = 'System';
			$ip = $attachmentHandler->get_user_ip();
			$attachmentHandler->log_activity_to_db( $severity, $time, $ip, $sender, $event_type, $log_message );
		}
	}



	/**
	 * Sends a notification message to a configured Slack webhook.
	 *
	 * This function formats a message with an optional emoji and sends it to the Slack webhook URL
	 * specified in the plugin's comment settings.
	 *
	 * @param string $message The message to send to Slack.
	 * @param string $emoji   An optional emoji to prepend to the message.
	 * @return void
	 */
	private function wpnts_notify_slack( $message, $emoji = '' ) {
		$formatted_message = $emoji . ' ' . $message;
		
		// Use SlackChannelRouter for channel and user tag support
		SlackChannelRouter::send_notification_with_routing(
			'wpntswebhook_website_downtime_alerts',
			$formatted_message
		);
	}
}
