<?php
/**
 * DRBU_Freemius_Hooks — Freemius lifecycle hook-ovi.
 *
 * Freemius SDK poziva ove hook-ove kada se desi važan događaj u životnom
 * ciklusu licence (povezivanje naloga, kupovina, aktivacija/deaktivacija
 * license key-a). Handleri samo osvežavaju keš licence, loguju događaj i
 * (opciono) prikazuju admin notifikaciju — bez teške logike koja bi mogla
 * da padne tokom SDK event-a.
 *
 * Kada SDK nije prisutan hook-ovi se nikad ne pokreću, a direktni pozivi
 * handlera (unit testovi) su bezbedni jer koriste function_exists guard-ove.
 *
 * @package discount-rules-box-upsell
 */

defined( 'ABSPATH' ) || exit;

class DRBU_Freemius_Hooks {

	/**
	 * Registruje lifecycle hook-ove.
	 *
	 * VAŽNA NAPOMENA (ispravljen bug): Freemius SDK interno prefiksuje SVE
	 * svoje "per-module" hook-ove (uključujući 'after_account_connection' i
	 * 'after_uninstall') u 'fs_{tag}_{module_affix}' — vidi
	 * Freemius::get_action_tag() / do_action() u
	 * vendor/freemius/wordpress-sdk/includes/class-freemius.php. Registracija
	 * preko obične WordPress add_action('after_account_connection', ...)
	 * NIKAD nije hvatala pravi hook (pogrešno ime), pa je ceo lifecycle sistem
	 * ćutke bio mrtav osim za 'after_uninstall' (koji je već ispravno išao
	 * kroz drbu_fs()->add_action()). Ispravan način je UVEK
	 * drbu_fs()->add_action( 'tag', ... ), koja sama radi tu transformaciju.
	 *
	 * Takođe, 'after_purchased', 'after_license_key_activation' i
	 * 'after_license_key_deactivation' uopšte NE POSTOJE u ovom SDK-u — nijedan
	 * do_action() poziv se ne dešava pod tim imenima. Stvarni hook za sve
	 * promene stanja licence/plana (kupovina, aktivacija, deaktivacija,
	 * isticanje, otkazivanje, start/isticanje trial-a) je 'after_license_change',
	 * sa $plan_change parametrom koji kaže o kojoj tranziciji je reč.
	 */
	public static function init() {
		add_action( 'admin_notices', array( __CLASS__, 'admin_notice' ) );

		if ( function_exists( 'drbu_fs' ) && drbu_fs() ) {
			drbu_fs()->add_action( 'after_account_connection', array( __CLASS__, 'on_after_account_connection' ) );
			drbu_fs()->add_action( 'after_license_change', array( __CLASS__, 'on_after_license_change' ), 10, 2 );
			drbu_fs()->add_action( 'after_uninstall', array( __CLASS__, 'on_after_uninstall' ) );

			// Vidi maybe_activate_license_for_unregistered_site() — presreće
			// Freemius-ov sopstveni "Activate License" AJAX PRE njegovog
			// handlera (niži prioritet = ranije), za slučaj koji taj handler
			// ne pokriva (sajt koji nikad nije opt-in-ovan na Freemius).
			add_action(
				'wp_ajax_' . drbu_fs()->get_ajax_action( 'activate_license' ),
				array( __CLASS__, 'maybe_activate_license_for_unregistered_site' ),
				1
			);
		}
	}

	/**
	 * Freemius-ov sopstveni "Activate License" dijalog (native SDK template,
	 * vendor/freemius/wordpress-sdk/templates/forms/license-activation.php)
	 * pretpostavlja da je sajt VEĆ registrovan/povezan na Freemius — interno
	 * poziva privatnu Freemius::activate_license(), koja radi PUT na
	 * postojeći install. Ako sajt nikad nije opt-in-ovan (podrazumevano
	 * ponašanje ovog plugina — 'anonymous_mode' je namerno true dok
	 * korisnik sam ne odluči da se poveže; vidi discount-rules-box-upsell.php),
	 * taj poziv tiho ne uspeva — dugme ostaje zaglavljeno na
	 * "Activating license..." zauvek, bez ijedne vidljive greške.
	 *
	 * Uzrok i rešenje potvrđeni LIVE testiranjem (ne samo čitanjem koda):
	 * Freemius::opt_in() pozvan sa email-om I license key-em ZAJEDNO
	 * ispravno radi i registraciju i aktivaciju licence u jednom koraku,
	 * čak i za sajt koji nikad nije bio povezan — dok activate_license()
	 * to ne ume.
	 *
	 * Ova metoda presreće TAJ isti AJAX poziv (isto action ime preko
	 * get_ajax_action(), isti 'security' nonce, isti POST format kao native
	 * dijalog) na nižem prioritetu (1, pre Freemius-ovog default
	 * prioriteta 10 — vidi WP_FS__DEFAULT_PRIORITY), i SAMO kad sajt nije
	 * registrovan radi opt_in() umesto activate_license(), pa odgovara u
	 * istom JSON formatu koji native dijalog-ov JS očekuje
	 * ({success:true,next_page:url} / {success:false,error:{message:...}}).
	 * Kad JESTE registrovan, odmah se vraća (return) i pušta Freemius-ov
	 * sopstveni, dokazano ispravan handler da normalno obradi zahtev —
	 * ništa se ne duplira niti menja za taj, već radni slučaj.
	 */
	public static function maybe_activate_license_for_unregistered_site() {
		if ( ! function_exists( 'drbu_fs' ) || ! drbu_fs() ) {
			return;
		}
		$fs = drbu_fs();

		if ( $fs->is_registered() ) {
			// Normalan slučaj — pusti Freemius-ov sopstveni handler da radi.
			return;
		}

		check_ajax_referer( $fs->get_ajax_action( 'activate_license' ), 'security' );

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json(
				array(
					'success' => false,
					'error'   => array( 'message' => __( 'Permission denied.', 'drbu-discount-rules-box-for-woocommerce' ) ),
				)
			);
		}

		$license_key = isset( $_POST['license_key'] ) ? sanitize_text_field( trim( wp_unslash( $_POST['license_key'] ) ) ) : '';
		if ( '' === $license_key ) {
			wp_send_json(
				array(
					'success' => false,
					'error'   => array( 'message' => __( 'Please enter a license key.', 'drbu-discount-rules-box-for-woocommerce' ) ),
				)
			);
		}

		$current_user = wp_get_current_user();
		$email        = ( $current_user && $current_user->exists() ) ? $current_user->user_email : '';

		$result = $fs->opt_in( $email, false, false, $license_key, false, false, false, null, array(), false );

		if ( is_string( $result ) && '' !== $result ) {
			// opt_in() vraća sopstveni Freemius URL kad uspe (potvrđeno live
			// testiranjem) — obično admin.php?page={slug}-account. NE
			// koristimo ga direktno: ovaj plugin namerno uklanja Freemius-ovu
			// nativnu "Account" podstranicu iz menija (remove_submenu_page()
			// u DRBU_Settings — ima sopstveni Account tab unutar glavne
			// stranice umesto toga), pa bi taj URL doveo do "Sorry, you are
			// not allowed to access this page." (potvrđeno live testiranjem:
			// stranica uopšte nije registrovana u $submenu nizu). Umesto
			// toga, uvek vodimo na našu sopstvenu, stvarno postojeću stranicu.
			wp_send_json(
				array(
					'success'   => true,
					'next_page' => admin_url( 'admin.php?page=' . DRBU_Settings::MENU_SLUG ),
				)
			);
		}

		if ( is_array( $result ) && isset( $result['error'] ) ) {
			wp_send_json(
				array(
					'success' => false,
					'error'   => array(
						'message' => is_string( $result['error'] )
							? $result['error']
							: __( 'License activation failed.', 'drbu-discount-rules-box-for-woocommerce' ),
					),
				)
			);
		}

		// Odbrambena provera: ako opt_in() nije vratio jasan string/error
		// oblik, oslanjamo se na stvarno stanje posle poziva. Isti razlog kao
		// gore — vodimo na našu stranicu, ne na uklonjenu Freemius "-account".
		if ( $fs->is_registered() && $fs->can_use_premium_code() ) {
			wp_send_json(
				array(
					'success'   => true,
					'next_page' => admin_url( 'admin.php?page=' . DRBU_Settings::MENU_SLUG ),
				)
			);
		}

		wp_send_json(
			array(
				'success' => false,
				'error'   => array( 'message' => __( 'Could not activate this license key. Please double-check it and try again.', 'drbu-discount-rules-box-for-woocommerce' ) ),
			)
		);
	}

	/**
	 * Deinstalacija plugina (poziva Freemius SDK nakon deinstalacije).
	 */
	public static function on_after_uninstall() {
		delete_option( 'drbu_options' );
		delete_option( 'drbu_license_last_sync' );
		delete_transient( 'drbu_cart_version' );
	}

	/**
	 * Nakon povezivanja naloga na Freemius.
	 *
	 * @param mixed $fs Freemius objekat ili null.
	 */
	public static function on_after_account_connection( $fs = null ) {
		self::handle_event( 'after_account_connection', $fs );
	}

	/**
	 * Nakon svake promene stanja licence/plana (Freemius SDK hook).
	 *
	 * Pokriva: kupovinu, aktivaciju/deaktivaciju license key-a, isticanje,
	 * otkazivanje, start i isticanje trial-a — sve kroz jedan hook, gde
	 * $plan_change kaže o kojoj tranziciji je reč (npr. 'upgraded',
	 * 'activated', 'downgraded', 'cancelled', 'expired', 'trial_started',
	 * 'trial_expired', 'extended', 'changed', 'none').
	 *
	 * @param string $plan_change Vrsta promene.
	 * @param mixed  $plan        Freemius plan objekat.
	 */
	public static function on_after_license_change( $plan_change = '', $plan = null ) {
		self::handle_event( (string) $plan_change, $plan );
	}

	/**
	 * Zajednička obrada: osveži keš, loguj, notifikuj.
	 *
	 * @param string $event Naziv događaja.
	 * @param mixed  $fs    Freemius objekat ili null.
	 */
	private static function handle_event( $event, $fs ) {
		if ( function_exists( 'drbu_license' ) ) {
			drbu_license()->refresh_cache();
		}
		self::log( $event, $fs );
		self::notify( $event );
	}

	/**
	 * Debug log (samo kada je WP_DEBUG uključen).
	 *
	 * @param string $event Naziv događaja.
	 * @param mixed  $fs    Freemius objekat ili null.
	 */
	private static function log( $event, $fs = null ) {
		if ( ! ( defined( 'WP_DEBUG' ) && WP_DEBUG ) ) {
			return;
		}
		$extra = '';
		if ( is_object( $fs ) && method_exists( $fs, 'is_registered' ) ) {
			$extra = ' registered=' . ( $fs->is_registered() ? 'yes' : 'no' );
		}
		// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
		error_log( sprintf( '[DRBU] Freemius lifecycle event: %s%s', $event, $extra ) );
	}

	/**
	 * Kratka admin notifikacija o promeni licence.
	 *
	 * @param string $event Naziv događaja.
	 */
	private static function notify( $event ) {
		if ( ! function_exists( 'set_transient' ) ) {
			return;
		}
		$message = self::event_label( $event );
		if ( '' !== $message ) {
			set_transient( 'drbu_license_event_notice', $message, 300 );
		}
	}

	/**
	 * Prikazuje sačuvanu notifikaciju o promeni licence (jednokratno).
	 */
	public static function admin_notice() {
		if ( ! function_exists( 'get_transient' ) || ! function_exists( 'current_user_can' ) ) {
			return;
		}
		if ( ! current_user_can( 'manage_woocommerce' ) ) {
			return;
		}
		$message = get_transient( 'drbu_license_event_notice' );
		if ( empty( $message ) ) {
			return;
		}
		delete_transient( 'drbu_license_event_notice' );
		printf(
			'<div class="notice notice-success is-dismissible"><p>%s</p></div>',
			esc_html( $message )
		);
	}

	/**
	 * Prevodi događaj u čitljivu poruku.
	 *
	 * @param string $event Naziv događaja.
	 * @return string
	 */
	private static function event_label( $event ) {
		$labels = array(
			'after_account_connection'           => __( 'Discount Rules Box: account connected to Freemius. License status has been refreshed.', 'drbu-discount-rules-box-for-woocommerce' ),
			// Vrednosti $plan_change iz Freemius 'after_license_change' hook-a.
			'upgraded'                            => __( 'Discount Rules Box: purchase confirmed. Pro features are now active.', 'drbu-discount-rules-box-for-woocommerce' ),
			'activated'                           => __( 'Discount Rules Box: license key activated. Pro features are now active.', 'drbu-discount-rules-box-for-woocommerce' ),
			'trial_started'                       => __( 'Discount Rules Box: 30-day Pro trial started. Pro features are now active.', 'drbu-discount-rules-box-for-woocommerce' ),
			'trial_expired'                       => __( 'Discount Rules Box: Pro trial has expired. The plugin is back on the Free plan.', 'drbu-discount-rules-box-for-woocommerce' ),
			'downgraded'                          => __( 'Discount Rules Box: license expired. The plugin is back on the Free plan.', 'drbu-discount-rules-box-for-woocommerce' ),
			'cancelled'                           => __( 'Discount Rules Box: subscription cancelled.', 'drbu-discount-rules-box-for-woocommerce' ),
			'expired'                             => __( 'Discount Rules Box: license has expired.', 'drbu-discount-rules-box-for-woocommerce' ),
			'changed'                             => __( 'Discount Rules Box: your plan has changed.', 'drbu-discount-rules-box-for-woocommerce' ),
		);

		return isset( $labels[ $event ] ) ? $labels[ $event ] : '';
	}
}
