<?php
/**
 * Plugin Name:       Waitlytics – Back in Stock Alerts for WooCommerce
 * Description:       AI stock forecasting, back-in-stock notifications & smart inventory for WooCommerce.
 * Version:           1.0.0
 * Requires at least: 6.0
 * Requires PHP:      7.4
 * Author:            Eshban Bahadur
 * Author URI:        https://www.linkedin.com/in/eshbanbahadur/
 * License:           GPL-2.0-or-later
 * License URI:       https://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain:       waitlytics
 * Domain Path:       /languages
 * WC requires at least: 7.0
 * WC tested up to:   9.6
 */

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

// Plugin constants.
define( 'WTLY_VERSION', '1.0.0' );
define( 'WTLY_PLUGIN_FILE', __FILE__ );
define( 'WTLY_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
define( 'WTLY_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
define( 'WTLY_PLUGIN_BASENAME', plugin_basename( __FILE__ ) );

// ─── Freemius SDK Init (must be first) ─────────────────────────────────────────
if ( ! function_exists( 'wtly_fs' ) ) {
	/**
	 * Create a helper function for easy SDK access.
	 *
	 * @return Freemius
	 */
	function wtly_fs() {
		global $wtly_fs;

		if ( ! isset( $wtly_fs ) ) {
			require_once WTLY_PLUGIN_DIR . 'vendor/freemius/start.php';

			$wtly_fs = fs_dynamic_init( array(
				'id'                  => '26068',
				'slug'                => 'waitlytics',
				'type'                => 'plugin',
				'public_key'          => 'pk_ac6dfa80c08c447c154e17bff91b9',
				'is_premium'          => false,
				'premium_suffix'      => 'Pro',
				'has_premium_version' => true,
				'has_addons'          => false,
				'has_paid_plans'      => true,
				'is_org_compliant'    => true,
				'trial'               => array(
					'days'               => 7,
					'is_require_payment' => false,
				),
				'menu'                => array(
					'slug'    => 'waitlytics',
					'support' => false,
					'account' => true,
				),
				'is_live'             => true,
			) );
		}

		return $wtly_fs;
	}

	wtly_fs();
	do_action( 'wtly_fs_loaded' );

	// Signal that the SDK was initiated.
	wtly_fs()->add_action( 'after_uninstall', 'wtly_fs_uninstall_cleanup' );
}

/**
 * Freemius uninstall cleanup callback.
 *
 * Fired via the Freemius 'after_uninstall' action when the plugin is deleted.
 * Removes ALL plugin data from the database.
 */
function wtly_fs_uninstall_cleanup() {
	global $wpdb;

	// Delete custom tables. One-time uninstall cleanup of our own custom tables;
	// caching and prepared-statement sniffs do not apply to DROP TABLE on a
	// $wpdb->prefix-derived table name.
	// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
	$wpdb->query( "DROP TABLE IF EXISTS {$wpdb->prefix}wtly_subscribers" );
	$wpdb->query( "DROP TABLE IF EXISTS {$wpdb->prefix}wtly_notifications_log" );
	$wpdb->query( "DROP TABLE IF EXISTS {$wpdb->prefix}wtly_forecasts" );
	// phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter

	// Delete options.
	delete_option( 'wtly_settings' );
	delete_option( 'wtly_db_version' );
	delete_option( 'wtly_version' );
	delete_option( 'wtly_activation_time' );
	delete_option( 'wtly_forecast_last_run' );

	// Delete post meta.
	delete_post_meta_by_key( '_wtly_disable_notify_form' );
	delete_post_meta_by_key( '_wtly_custom_email_message' );
	delete_post_meta_by_key( '_wtly_forecast_data' );

	// Clear scheduled events.
	wp_clear_scheduled_hook( 'wtly_check_stock_changes' );
	wp_clear_scheduled_hook( 'wtly_cleanup_expired_subscriptions' );
	wp_clear_scheduled_hook( 'wtly_run_ai_forecast' );
	wp_clear_scheduled_hook( 'wtly_weekly_report_email' );
	wp_clear_scheduled_hook( 'wtly_send_notification_batch' );

	// Delete all transients with our prefix. One-time uninstall cleanup; object
	// caching is irrelevant here and the LIKE pattern is a fixed literal.
	// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
	$wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE '%wtly_%'" );
}

/**
 * Check if Pro features are available.
 *
 * @return bool
 */
function wtly_is_pro() {
	// Dev override for local testing.
	if ( defined( 'WTLY_FORCE_PRO' ) && WTLY_FORCE_PRO ) {
		return true;
	}
	if ( ! function_exists( 'wtly_fs' ) ) {
		return false;
	}
	return wtly_fs()->is_paying() || wtly_fs()->is_plan( 'pro', true );
}

// ─── Free version auto-deactivation ────────────────────────────────────────────
wtly_fs()->set_basename( true, __FILE__ );

// ─── WooCommerce Dependency Check ──────────────────────────────────────────────

/**
 * Check if WooCommerce is active.
 *
 * @return bool
 */
function wtly_check_requirements() {
	if ( ! class_exists( 'WooCommerce' ) ) {
		add_action( 'admin_notices', 'wtly_woocommerce_missing_notice' );
		return false;
	}
	return true;
}

/**
 * Display admin notice when WooCommerce is not active.
 */
function wtly_woocommerce_missing_notice() {
	$screen = get_current_screen();
	if ( null !== $screen && 'plugins' === $screen->id ) {
		printf(
			'<div class="notice notice-error"><p>%s</p></div>',
			esc_html__( 'Waitlytics requires WooCommerce to be installed and activated.', 'waitlytics' )
		);
	}
}

// ─── HPOS Compatibility ────────────────────────────────────────────────────────
add_action( 'before_woocommerce_init', function () {
	if ( class_exists( \Automattic\WooCommerce\Utilities\FeaturesUtil::class ) ) {
		\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility(
			'custom_order_tables',
			__FILE__,
			true
		);
	}
} );

// ─── Activation / Deactivation ─────────────────────────────────────────────────
// These classes must be loaded at plugin parse time, not deferred to
// plugins_loaded, because register_activation_hook fires before plugins_loaded.
require_once WTLY_PLUGIN_DIR . 'includes/class-wtly-activator.php';
require_once WTLY_PLUGIN_DIR . 'includes/class-wtly-deactivator.php';

register_activation_hook( __FILE__, array( 'WTLY_Activator', 'activate' ) );
register_deactivation_hook( __FILE__, array( 'WTLY_Deactivator', 'deactivate' ) );

// ─── Bootstrap ─────────────────────────────────────────────────────────────────
add_action( 'plugins_loaded', 'wtly_init_plugin' );

/**
 * Initialize the plugin after all plugins are loaded.
 */
function wtly_init_plugin() {
	if ( ! wtly_check_requirements() ) {
		return;
	}

	// Load includes.
	require_once WTLY_PLUGIN_DIR . 'includes/class-wtly-loader.php';

	// Core classes.
	require_once WTLY_PLUGIN_DIR . 'includes/core/class-wtly-subscriber.php';
	require_once WTLY_PLUGIN_DIR . 'includes/core/class-wtly-notification.php';
	require_once WTLY_PLUGIN_DIR . 'includes/core/class-wtly-stock-monitor.php';
	require_once WTLY_PLUGIN_DIR . 'includes/core/class-wtly-form-handler.php';
	require_once WTLY_PLUGIN_DIR . 'includes/core/class-wtly-email-templates.php';
	require_once WTLY_PLUGIN_DIR . 'includes/core/class-wtly-dashboard.php';

	// Admin.
	if ( is_admin() ) {
		require_once WTLY_PLUGIN_DIR . 'admin/class-wtly-admin.php';
		require_once WTLY_PLUGIN_DIR . 'admin/class-wtly-settings.php';
	}

	// Public.
	if ( ! is_admin() || wp_doing_ajax() ) {
		require_once WTLY_PLUGIN_DIR . 'public/class-wtly-public.php';
	}

	// PRO classes.
	if ( wtly_is_pro() ) {
		$pro_dir = WTLY_PLUGIN_DIR . 'includes/pro/';
		if ( is_dir( $pro_dir ) ) {
			require_once $pro_dir . 'class-wtly-analytics.php';
			require_once $pro_dir . 'class-wtly-forecasting.php';
			require_once $pro_dir . 'class-wtly-ai-service.php';
			require_once $pro_dir . 'class-wtly-integrations.php';
			require_once $pro_dir . 'class-wtly-sms-notifications.php';
			require_once $pro_dir . 'class-wtly-popup.php';
			require_once $pro_dir . 'class-wtly-custom-emails.php';
			require_once $pro_dir . 'class-wtly-csv-export.php';
			require_once $pro_dir . 'class-wtly-recaptcha.php';
			require_once $pro_dir . 'class-wtly-double-optin.php';
			require_once $pro_dir . 'class-wtly-my-account.php';
			require_once $pro_dir . 'class-wtly-shortcode.php';
			require_once $pro_dir . 'class-wtly-pro-admin.php';

			// Initialize PRO classes.
			$forecasting = new WTLY_Forecasting();
			$forecasting->init();

			$integrations = new WTLY_Integrations();
			$integrations->init();

			$sms = new WTLY_SMS_Notifications();
			$sms->init();

			$popup = new WTLY_Popup();
			$popup->init();

			$custom_emails = new WTLY_Custom_Emails();
			$custom_emails->init();

			$csv_export = new WTLY_CSV_Export();
			$csv_export->init();

			$recaptcha = new WTLY_Recaptcha();
			$recaptcha->init();

			$double_optin = new WTLY_Double_Optin();
			$double_optin->init();

			$my_account = new WTLY_My_Account();
			$my_account->init();

			$shortcode = new WTLY_Shortcode();
			$shortcode->init();

			$pro_admin = new WTLY_Pro_Admin();
			$pro_admin->init();
		}
	}

	// Text domain loading is handled automatically by WordPress 4.6+ for
	// plugins hosted on WordPress.org, so no load_plugin_textdomain() call.

	// Initialize core classes.
	$stock_monitor = new WTLY_Stock_Monitor();
	$stock_monitor->init();

	$form_handler = new WTLY_Form_Handler();
	$form_handler->init();

	// Admin.
	if ( is_admin() ) {
		$admin = new WTLY_Admin();
		$admin->init();

		$settings = new WTLY_Settings();
		$settings->init();
	}

	// Public.
	if ( ! is_admin() || wp_doing_ajax() ) {
		$public = new WTLY_Public();
		$public->init();
	}
}

/**
 * Get plugin settings with defaults.
 *
 * @return array
 */
function wtly_get_settings() {
	$defaults = array(
		// General.
		'enable_notifications'        => true,
		'notification_position'       => 'after_add_to_cart',
		'show_subscriber_count'       => false,
		'guest_subscriptions'         => true,

		// Email — Notification.
		'email_from_name'             => '',
		'email_from_address'          => '',
		'email_subject'               => '',
		'email_heading'               => '',
		'email_body'                  => '',
		'email_include_product_image' => true,
		'email_include_price'         => true,
		'email_include_cta_button'    => true,

		// Admin Alerts.
		'admin_notify_new_subscriber' => true,
		'admin_notify_email'          => '',
		'low_stock_threshold'         => 5,
		'admin_low_stock_email'       => true,

		// Form Appearance.
		'form_button_text'            => '',
		'form_success_message'        => '',
		'form_placeholder_text'       => '',

		// PRO: AI Settings.
		'ai_provider'                 => 'openai',
		'ai_api_key'                  => '',
		'ai_model'                    => 'gpt-4o-mini',
		'ai_forecast_frequency'       => 'weekly',
		'ai_auto_forecast'            => false,

		// PRO: Integrations.
		'mailchimp_api_key'           => '',
		'mailchimp_list_id'           => '',
		'klaviyo_api_key'             => '',
		'klaviyo_list_id'             => '',
		'twilio_sid'                  => '',
		'twilio_token'                => '',
		'twilio_from_number'          => '',
		'whatsapp_enabled'            => false,

		// PRO: Form Advanced.
		'popup_enabled'               => false,
		'popup_delay_seconds'         => 3,
		'popup_show_on'               => 'out_of_stock',
		'custom_form_css'             => '',

		// PRO: Protection.
		'recaptcha_enabled'           => false,
		'recaptcha_site_key'          => '',
		'recaptcha_secret_key'        => '',
		'double_optin_enabled'        => false,
		'banned_emails'               => '',
		'banned_domains'              => '',
	);

	return wp_parse_args(
		get_option( 'wtly_settings', array() ),
		$defaults
	);
}

// ─── Cron Event Callbacks ───────────────────────────────────────────────────────
add_action( 'wtly_check_stock_changes', 'wtly_cron_check_stock_changes' );
add_action( 'wtly_cleanup_expired_subscriptions', 'wtly_cron_cleanup_expired' );
add_action( 'wtly_send_notification_batch', 'wtly_cron_send_notification_batch', 10, 3 );

/**
 * Cron: backup stock check for products with active subscribers.
 *
 * Catches manual DB changes that bypass WooCommerce hooks.
 */
function wtly_cron_check_stock_changes() {
	if ( ! class_exists( 'WTLY_Subscriber' ) || ! class_exists( 'WTLY_Notification' ) ) {
		return;
	}

	global $wpdb;

	// Find products that are now in stock but have active subscribers.
	// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
	$products = $wpdb->get_results(
		$wpdb->prepare(
			"SELECT DISTINCT s.product_id, s.variation_id
			FROM {$wpdb->prefix}wtly_subscribers s
			INNER JOIN {$wpdb->postmeta} pm ON s.product_id = pm.post_id
			WHERE s.status = %s
			AND pm.meta_key = '_stock_status'
			AND pm.meta_value = 'instock'",
			'active'
		)
	);
	// phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter

	if ( empty( $products ) ) {
		return;
	}

	$notification = new WTLY_Notification();
	foreach ( $products as $row ) {
		$notification->send_back_in_stock_notifications(
			absint( $row->product_id ),
			absint( $row->variation_id )
		);
	}
}

/**
 * Cron: clean up expired subscriptions older than 180 days.
 */
function wtly_cron_cleanup_expired() {
	global $wpdb;

	// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
	$wpdb->query(
		$wpdb->prepare(
			"DELETE FROM {$wpdb->prefix}wtly_subscribers
			WHERE status = %s
			AND notified_at < DATE_SUB(NOW(), INTERVAL 180 DAY)",
			'notified'
		)
	);
	// phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
}

/**
 * Cron: process remaining notification batches.
 *
 * @param int $product_id   Product ID.
 * @param int $variation_id Variation ID.
 * @param int $batch_size   Batch size.
 */
function wtly_cron_send_notification_batch( $product_id, $variation_id, $batch_size ) {
	if ( ! class_exists( 'WTLY_Notification' ) ) {
		return;
	}

	$notification = new WTLY_Notification();
	$notification->send_back_in_stock_notifications( absint( $product_id ), absint( $variation_id ) );
}

// ─── Custom Cron Schedule ──────────────────────────────────────────────────────
add_filter( 'cron_schedules', 'wtly_add_cron_intervals' );

/**
 * Add custom cron intervals.
 *
 * @param array $schedules Existing cron schedules.
 * @return array
 */
function wtly_add_cron_intervals( $schedules ) {
	$schedules['wtly_six_hours'] = array(
		'interval' => 6 * HOUR_IN_SECONDS,
		'display'  => esc_html__( 'Every Six Hours', 'waitlytics' ),
	);
	return $schedules;
}
