<?php
/**
 * The core plugin class.
 *
 * @package Lucrativeit_Subscription_Recurring_Billing
 */

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

/**
 * Main bootstrap / service container for the plugin.
 */
final class LUCRSURE_Plugin {

	/**
	 * Singleton instance.
	 *
	 * @var LUCRSURE_Plugin|null
	 */
	private static $instance = null;

	/**
	 * Settings handler.
	 *
	 * @var LUCRSURE_Settings
	 */
	public $settings;

	/**
	 * Admin controller.
	 *
	 * @var LUCRSURE_Admin
	 */
	public $admin;

	/**
	 * Retrieve the singleton instance.
	 *
	 * @return LUCRSURE_Plugin
	 */
	public static function instance() {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	/**
	 * Constructor.
	 */
	private function __construct() {
		$this->includes();
		$this->init_hooks();
	}

	/**
	 * Include required files.
	 */
	private function includes() {
		// Core helpers.
		require_once LUCRSURE_PLUGIN_DIR . 'includes/helpers.php';

		// Database layer.
		require_once LUCRSURE_PLUGIN_DIR . 'includes/db/class-lucrsure-repository.php';
		require_once LUCRSURE_PLUGIN_DIR . 'includes/db/class-lucrsure-branch-repository.php';
		require_once LUCRSURE_PLUGIN_DIR . 'includes/db/class-lucrsure-customer-repository.php';
		require_once LUCRSURE_PLUGIN_DIR . 'includes/db/class-lucrsure-plan-repository.php';
		require_once LUCRSURE_PLUGIN_DIR . 'includes/db/class-lucrsure-plan-category-repository.php';
		require_once LUCRSURE_PLUGIN_DIR . 'includes/db/class-lucrsure-subscription-repository.php';
		require_once LUCRSURE_PLUGIN_DIR . 'includes/db/class-lucrsure-invoice-repository.php';
		require_once LUCRSURE_PLUGIN_DIR . 'includes/db/class-lucrsure-role-repository.php';
		require_once LUCRSURE_PLUGIN_DIR . 'includes/db/class-lucrsure-staff-repository.php';

		// Settings.
		require_once LUCRSURE_PLUGIN_DIR . 'includes/class-lucrsure-settings.php';

		// Payment gateways.
		require_once LUCRSURE_PLUGIN_DIR . 'includes/gateways/interface-lucrsure-gateway.php';
		require_once LUCRSURE_PLUGIN_DIR . 'includes/gateways/abstract-lucrsure-gateway.php';
		require_once LUCRSURE_PLUGIN_DIR . 'includes/gateways/class-lucrsure-manual-gateway.php';
		require_once LUCRSURE_PLUGIN_DIR . 'includes/gateways/class-lucrsure-stripe-gateway.php';
		require_once LUCRSURE_PLUGIN_DIR . 'includes/gateways/class-lucrsure-sslcommerz-gateway.php';
		require_once LUCRSURE_PLUGIN_DIR . 'includes/gateways/class-lucrsure-razorpay-gateway.php';
		require_once LUCRSURE_PLUGIN_DIR . 'includes/gateways/class-lucrsure-paypal-gateway.php';
		require_once LUCRSURE_PLUGIN_DIR . 'includes/gateways/class-lucrsure-gateway-manager.php';

		// Emails.
		require_once LUCRSURE_PLUGIN_DIR . 'includes/class-lucrsure-emails.php';
		require_once LUCRSURE_PLUGIN_DIR . 'includes/class-lucrsure-invoice-pdf.php';
		require_once LUCRSURE_PLUGIN_DIR . 'includes/class-lucrsure-dependencies.php';

		// Billing engine.
		require_once LUCRSURE_PLUGIN_DIR . 'includes/class-lucrsure-billing-engine.php';

		// Demo data seeder.
		require_once LUCRSURE_PLUGIN_DIR . 'includes/class-lucrsure-demo-data.php';
		require_once LUCRSURE_PLUGIN_DIR . 'includes/class-lucrsure-plan-pages.php';

		// Reports.
		require_once LUCRSURE_PLUGIN_DIR . 'includes/class-lucrsure-reports.php';

		// REST webhooks.
		require_once LUCRSURE_PLUGIN_DIR . 'includes/class-lucrsure-webhooks.php';

		// Public shortcodes / checkout.
		require_once LUCRSURE_PLUGIN_DIR . 'includes/class-lucrsure-frontend.php';
		LUCRSURE_Frontend::register_ajax_handlers();

		// Integrations.
		require_once LUCRSURE_PLUGIN_DIR . 'includes/integrations/class-lucrsure-woocommerce.php';

		// Admin.
		if ( is_admin() ) {
			require_once LUCRSURE_PLUGIN_DIR . 'admin/class-lucrsure-admin.php';
			require_once LUCRSURE_PLUGIN_DIR . 'admin/class-lucrsure-admin-handler.php';
		}
	}

	/**
	 * Register the core WordPress hooks.
	 */
	private function init_hooks() {
		add_action( 'init', array( $this, 'init' ) );
	}

	/**
	 * Initialise plugin services.
	 */
	public function init() {
		require_once LUCRSURE_PLUGIN_DIR . 'includes/class-lucrsure-activator.php';
		LUCRSURE_Activator::maybe_migrate_legacy_prefix();

		lucrsure_maybe_upgrade_email_templates();
		lucrsure_maybe_upgrade_notifications();
		lucrsure_maybe_upgrade_email_branding();
		lucrsure_maybe_upgrade_pdf_invoice();
		lucrsure_maybe_upgrade_plan_schema();
		lucrsure_maybe_upgrade_branch_schema();
		lucrsure_maybe_upgrade_frontend_settings();
		lucrsure_maybe_repair_plan_categories();
		lucrsure_maybe_migrate_pro_gateways();
		lucrsure_maybe_upgrade_billing_address_schema();

		if ( is_admin() ) {
			add_action( 'admin_notices', array( $this, 'maybe_pro_addon_notice' ) );
		}

		LUCRSURE_Dependencies::init();
		if ( false === get_option( 'lucrsure_dependency_status', false ) ) {
			LUCRSURE_Dependencies::verify();
		}

		$this->settings = new LUCRSURE_Settings();

		// Initialise the chosen subscription engine.
		if ( 'woocommerce' === $this->settings->get( 'subscription_engine', 'custom' ) ) {
			LUCRSURE_WooCommerce::instance()->init();
		}

		LUCRSURE_Emails::init();
		LUCRSURE_Billing_Engine::instance()->init();
		LUCRSURE_Webhooks::instance()->init();
		add_action( 'template_redirect', array( $this, 'maybe_capture_paypal_return' ) );
		add_action( 'template_redirect', array( $this, 'maybe_capture_stripe_return' ) );
		add_action( 'template_redirect', array( $this, 'maybe_capture_sslcommerz_return' ) );
		add_action( 'template_redirect', array( $this, 'maybe_capture_razorpay_return' ) );

		LUCRSURE_Frontend::instance()->init();

		if ( is_admin() ) {
			$this->admin = new LUCRSURE_Admin( $this->settings );
			$this->admin->init();

			$handler = new LUCRSURE_Admin_Handler( $this->settings );
			$handler->init();
		}
	}

	/**
	 * Capture PayPal orders when the buyer returns from Checkout.
	 */
	public function maybe_capture_paypal_return() {
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Public payment return URL from PayPal.
		if ( empty( $_GET['lucrsure_payment'] ) || 'success' !== sanitize_key( wp_unslash( $_GET['lucrsure_payment'] ) ) ) {
			return;
		}

		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Public payment return URL from PayPal.
		$gateway = isset( $_GET['lucrsure_gateway'] ) ? sanitize_key( wp_unslash( $_GET['lucrsure_gateway'] ) ) : '';
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Public payment return URL from PayPal.
		$token = isset( $_GET['token'] ) ? sanitize_text_field( wp_unslash( $_GET['token'] ) ) : '';

		if ( 'paypal' !== $gateway || '' === $token ) {
			return;
		}

		// PayPal order ids are alphanumeric (optionally with dashes/underscores).
		if ( ! preg_match( '/^[A-Za-z0-9_-]{1,64}$/', $token ) ) {
			return;
		}

		$paypal = new LUCRSURE_PayPal_Gateway();
		if ( ! $paypal->is_enabled() ) {
			return;
		}

		$paypal->capture_order( $token );
	}

	/**
	 * Verify Stripe Checkout when the buyer returns from payment.
	 *
	 * Webhooks remain the primary confirmation path; this is a fallback so
	 * invoices are marked paid (and confirmation emails sent) even when the
	 * webhook cannot reach the site (e.g. local development).
	 */
	public function maybe_capture_stripe_return() {
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Public payment return URL from Stripe.
		if ( empty( $_GET['lucrsure_payment'] ) || 'success' !== sanitize_key( wp_unslash( $_GET['lucrsure_payment'] ) ) ) {
			return;
		}

		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Public payment return URL from Stripe.
		$gateway = isset( $_GET['lucrsure_gateway'] ) ? sanitize_key( wp_unslash( $_GET['lucrsure_gateway'] ) ) : '';
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Public payment return URL from Stripe.
		$session_id = isset( $_GET['session_id'] ) ? sanitize_text_field( wp_unslash( $_GET['session_id'] ) ) : '';

		// Also accept a bare session_id on success URLs without lucrsure_gateway
		// (older sessions) when the id looks like a Stripe Checkout session.
		if ( 'stripe' !== $gateway && ! preg_match( '/^cs_/', $session_id ) ) {
			return;
		}

		if ( '' === $session_id || ! preg_match( '/^cs_[A-Za-z0-9_]+$/', $session_id ) ) {
			return;
		}

		$stripe = new LUCRSURE_Stripe_Gateway();
		if ( ! $stripe->is_enabled() ) {
			return;
		}

		$stripe->complete_checkout_return( $session_id );
	}

	/**
	 * Verify SSLCommerz when the buyer returns from payment.
	 *
	 * SSLCommerz may redirect with GET or POST (val_id + tran_id).
	 */
	public function maybe_capture_sslcommerz_return() {
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Public payment return URL from SSLCommerz.
		$status = isset( $_REQUEST['lucrsure_payment'] ) ? sanitize_key( wp_unslash( $_REQUEST['lucrsure_payment'] ) ) : '';
		if ( 'success' !== $status ) {
			return;
		}

		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Public payment return URL from SSLCommerz.
		$gateway = isset( $_REQUEST['lucrsure_gateway'] ) ? sanitize_key( wp_unslash( $_REQUEST['lucrsure_gateway'] ) ) : '';
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Public payment return URL from SSLCommerz.
		$val_id = isset( $_REQUEST['val_id'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['val_id'] ) ) : '';
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Public payment return URL from SSLCommerz.
		$tran_id = isset( $_REQUEST['tran_id'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['tran_id'] ) ) : '';

		if ( '' === $tran_id && isset( $_REQUEST['invoice'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
			$tran_id = sanitize_text_field( wp_unslash( $_REQUEST['invoice'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
		}

		// Require SSLCommerz markers so we do not collide with other gateways.
		if ( 'sslcommerz' !== $gateway && '' === $val_id ) {
			return;
		}

		if ( '' === $val_id || '' === $tran_id ) {
			return;
		}

		$ssl = new LUCRSURE_SSLCommerz_Gateway();
		if ( ! $ssl->is_enabled() ) {
			return;
		}

		$ssl->complete_return( $tran_id, $val_id );
	}

	/**
	 * Verify Razorpay Payment Link callbacks when the buyer returns.
	 */
	public function maybe_capture_razorpay_return() {
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Public payment return URL from Razorpay.
		$status = isset( $_GET['lucrsure_payment'] ) ? sanitize_key( wp_unslash( $_GET['lucrsure_payment'] ) ) : '';
		if ( 'success' !== $status ) {
			return;
		}

		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Public payment return URL from Razorpay.
		$gateway = isset( $_GET['lucrsure_gateway'] ) ? sanitize_key( wp_unslash( $_GET['lucrsure_gateway'] ) ) : '';
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Public payment return URL from Razorpay.
		$payment_id = isset( $_GET['razorpay_payment_id'] ) ? sanitize_text_field( wp_unslash( $_GET['razorpay_payment_id'] ) ) : '';
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Public payment return URL from Razorpay.
		$signature = isset( $_GET['razorpay_signature'] ) ? sanitize_text_field( wp_unslash( $_GET['razorpay_signature'] ) ) : '';

		if ( 'razorpay' !== $gateway && ( '' === $payment_id || '' === $signature ) ) {
			return;
		}

		if ( '' === $payment_id || '' === $signature ) {
			return;
		}

		$razorpay = new LUCRSURE_Razorpay_Gateway();
		if ( ! $razorpay->is_enabled() ) {
			return;
		}

		$razorpay->complete_return( wp_unslash( $_GET ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Sanitized inside complete_return().
	}

	/**
	 * Prompt admins to activate the Pro add-on when it is installed but inactive.
	 * Scoped to this plugin's screens and dismissible (Guideline 11).
	 */
	public function maybe_pro_addon_notice() {
		if ( ! current_user_can( 'activate_plugins' ) || lucrsure_is_pro() ) {
			return;
		}

		if ( ! lucrsure_pro_plugin_installed() || lucrsure_pro_plugin_is_active() ) {
			return;
		}

		if ( ! $this->is_plugin_admin_screen() ) {
			return;
		}

		if ( get_user_meta( get_current_user_id(), 'lucrsure_dismiss_pro_activate_notice', true ) ) {
			return;
		}

		$pro_basename = lucrsure_pro_plugin_basename();
		if ( '' === $pro_basename ) {
			$pro_basename = 'Lucrativeit-subscription-recurring-billing-pro/lucrativeit-subscription-plus-pro.php';
		}

		$activate_url = wp_nonce_url(
			admin_url( 'plugins.php?action=activate&plugin=' . rawurlencode( $pro_basename ) ),
			'activate-plugin_' . $pro_basename
		);
		$dismiss_url  = wp_nonce_url(
			admin_url( 'admin-post.php?action=lucrsure_dismiss_pro_activate_notice' ),
			'lucrsure_dismiss_pro_activate_notice'
		);

		echo '<div class="notice notice-warning is-dismissible"><p>';
		echo esc_html(
			sprintf(
				/* translators: %s: plugin name */
				__( '%s Pro is installed but not active. Activate the Pro add-on to unlock Premium features (email branding, PDF invoices, staff, reports, and reminders).', 'lucrativeit-subscription-recurring-billing' ),
				lucrsure_plugin_name()
			)
		);
		echo ' <a href="' . esc_url( $activate_url ) . '">' . esc_html__( 'Activate Pro add-on', 'lucrativeit-subscription-recurring-billing' ) . '</a>';
		echo ' | <a href="' . esc_url( $dismiss_url ) . '">' . esc_html__( 'Dismiss', 'lucrativeit-subscription-recurring-billing' ) . '</a>';
		echo '</p></div>';
	}

	/**
	 * Whether the current screen belongs to this plugin.
	 *
	 * @return bool
	 */
	protected function is_plugin_admin_screen() {
		if ( ! is_admin() || ! isset( $_GET['page'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
			return false;
		}

		$page = sanitize_text_field( wp_unslash( $_GET['page'] ) ); // phpcs:ignore WordPress.Security.NonceVerification

		return LUCRSURE_PLUGIN_SLUG === $page || 0 === strpos( $page, 'lucrsure-' );
	}
}
