<?php
/**
 * License helper functions.
 *
 * @package Awesomemotive\Rewardswp\Helpers
 * @since 1.0.0
 */

namespace Awesomemotive\Rewardswp\Helpers;

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

use Awesomemotive\Rewardswp\Database\UpgradeManager;
use Awesomemotive\Rewardswp\Services\FeatureGatingService;
use Awesomemotive\Rewardswp\Services\LicenseManagerService;
use Awesomemotive\Rewardswp\Settings\Options\General\LicenseOption;
use Exception;

/**
 * Check if user has a specific plan tier.
 *
 * @since 1.0.0
 *
 * @param string $plan The plan to check for ('basic', 'plus', 'pro', 'lite').
 * @return bool Whether the user has the specific plan.
 */
function is_rewardswp_plan( string $plan ): bool {
	return get_rewardswp_plan_tier() === $plan;
}

/**
 * Retrieve if it is the Lite plan.
 *
 * @since 1.0.0
 *
 * @return bool
 */
function is_rewardswp_lite_plan(): bool {
	return is_rewardswp_plan( 'lite' );
}

/**
 * Check if user has basic plan specifically.
 *
 * @since 1.0.0
 *
 * @return bool Whether the user has the basic plan.
 */
function is_rewardswp_basic_plan(): bool {
	return is_rewardswp_plan( 'basic' );
}

/**
 * Check if user has plus plan specifically.
 *
 * @since 1.0.0
 *
 * @return bool Whether the user has the plus plan.
 */
function is_rewardswp_plus_plan(): bool {
	return is_rewardswp_plan( 'plus' );
}

/**
 * Retrieve if it is the Pro plan.
 *
 * @since 1.0.0
 *
 * @return bool
 */
function is_rewardswp_pro_plan(): bool {
	return is_rewardswp_plan( 'pro' );
}

/**
 * Get the priority of a given plan.
 *
 * This allows us to compare license levels using numeric values,
 * making it easier to determine if an upgrade is required.
 *
 * @since 1.0.0
 *
 * @param string $plan The license plan slug (e.g., 'lite', 'pro').
 * @return int The priority of the plan. Unknown plans return 0.
 */
function get_plan_priority( string $plan ): int {
	$priorities = array(
		'lite'  => 1,
		'basic' => 2,
		'plus'  => 3,
		'pro'   => 4,
	);

	return $priorities[ $plan ] ?? 0;
}

/**
 * Retrieve if the license is valid.
 *
 * Be careful when using this function, since it always returns true for the Lite version.
 * If you need to check for a Pro specific feature, use in conjunction with is_rewardswp_pro_plan()
 *
 * @since 1.0.0
 *
 * @return bool Whether the license is valid or not.
 */
function is_license_valid(): bool {
	if ( is_rewardswp_lite_plan() ) {
		return true;
	}

	try {
		$license_manager_service = am_rewardswp()->get_container()->get( LicenseManagerService::class );

		$license_data = $license_manager_service->check_license_status();

		if ( is_wp_error( $license_data ) ) {
			return true; // Always assume it is valid on errors.
		}

		return 'valid' === ( $license_data['status'] ?? '' );

	} catch ( Exception $exception ) {
		return true; // Always assume it is valid on errors.
	}
}

/**
 * Check if the Pro version plugin file exists but is not active.
 *
 * @since 1.0.0
 *
 * @return bool True if Pro is installed but inactive, false otherwise.
 */
function is_rewardswp_pro_installed_but_inactive(): bool {
	if ( ! function_exists( 'get_plugins' ) ) {
		require_once ABSPATH . 'wp-admin/includes/plugin.php';
	}

	// Check if the is_plugin_active function exists, if not, load the plugin administration file.
	if ( ! function_exists( 'is_plugin_active' ) ) {
		require_once ABSPATH . 'wp-admin/includes/plugin.php';
	}

	$all_plugins     = get_plugins();
	$pro_plugin_path = 'rewardswp-pro/rewardswp.php';

	return isset( $all_plugins[ $pro_plugin_path ] ) && ! is_plugin_active( $pro_plugin_path );
}

/**
 * Check if this is a Pro build of the plugin.
 *
 * This checks for the existence of the /src/Pro folder, which is only
 * present in Pro builds. This is different from checking the license status -
 * a Pro build user may not have activated their license yet.
 *
 * @since 1.1.0
 *
 * @return bool True if this is a Pro build, false if Lite.
 */
function is_rewardswp_pro_build(): bool {
	return is_dir( AM_REWARDSWP_PLUGIN_DIR . '/src/Pro' );
}

/**
 * Check if we should behave as Pro build, respecting DevTools override.
 *
 * Unlike is_rewardswp_pro_build() which only checks if Pro files exist,
 * this function also respects the DevTools plan override for testing.
 *
 * @since 1.1.1
 *
 * @return bool True if Pro context (build is Pro AND not overridden to Lite).
 */
function is_rewardswp_pro_context(): bool {
	// Start with the actual build type.
	if ( ! is_rewardswp_pro_build() ) {
		return false;
	}

	// In debug mode, respect DevTools override.
	if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
		$devtools_override = get_option( 'rewardswp_devtools_plan_override', '' );
		if ( 'lite' === $devtools_override ) {
			return false;
		}
	}

	return true;
}

/**
 * Check if the Pro version is at least a specific version.
 *
 * @since 1.0.1
 *
 * @param string $version The version to check against.
 * @return bool Whether the Pro version is at least the specified version.
 */
function is_pro_version_at_least( string $version ): bool {
	if ( ! is_rewardswp_pro_plan() ) {
		return false;
	}

	$current_version = get_option( UpgradeManager::PRO_DB_VERSION_OPTION, '1.0.0' );

	return version_compare( $current_version, $version, '>=' );
}

/**
 * Get the specific plan tier from license data.
 *
 * This function retrieves the actual plan tier (basic, plus, pro) from stored license data
 * rather than just checking if it's lite or pro. Also validates license status.
 *
 * Priority order:
 * 1. DevTools override (wp_option, only in WP_DEBUG mode)
 * 2. Pro folder check (if folder doesn't exist, it's Lite)
 * 3. License data (normal behavior)
 *
 * @since 1.0.0
 *
 * @return string The plan tier: 'lite', 'basic', 'plus', or 'pro'.
 */
function get_rewardswp_plan_tier(): string {
	// Priority 1: Check DevTools override (only in debug mode for safety).
	if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
		$devtools_override = get_option( 'rewardswp_devtools_plan_override', '' );
		if ( ! empty( $devtools_override ) && in_array( $devtools_override, [ 'lite', 'basic', 'plus', 'pro' ], true ) ) {
			return $devtools_override;
		}
	}

	// Priority 2: Check if Pro folder exists (if not, it's a Lite install).
	if ( ! is_dir( AM_REWARDSWP_PLUGIN_DIR . '/src/Pro' ) ) {
		return 'lite';
	}

	// Priority 3: License data.
	$license_data = get_option_value( LicenseOption::class );

	if ( 'valid' === $license_data['status'] && ! empty( $license_data['price_id'] ) ) {
		return get_rewardswp_plan_tier_by_price_id( $license_data['price_id'] );
	}

	// If the customer has a Pro build installed and never activated a license, we fall back to basic.
	return get_rewardswp_plan_tier_by_price_id( 1 );
}

/**
 * Get the plan name for display purposes.
 *
 * @since 1.0.0
 *
 * @return string The plan name for display.
 */
function get_rewardswp_plan_name(): string {
	$license_data = get_option_value( LicenseOption::class );

	if ( ! empty( $license_data['plan_name'] ) ) {
		return $license_data['plan_name'];
	}

	// If no plan name can be found, fallback to one of the known names.
	$plan_tier = get_rewardswp_plan_tier();

	return get_rewardswp_plan_tier_names()[ $plan_tier ];
}

/**
 * Get tier names.
 *
 * @since 1.0.0
 *
 * @return string[]
 */
function get_rewardswp_plan_tier_names(): array {
	return [
		'lite'  => 'Lite',
		'basic' => 'Basic',
		'plus'  => 'Plus',
		'pro'   => 'Pro',
	];
}

/**
 * Get tier by price_id.
 *
 * @since 1.0.0
 *
 * @param int $price_id The price ID.
 *
 * @return string
 */
function get_rewardswp_plan_tier_by_price_id( int $price_id ): string {
	switch ( $price_id ) {
		case 1:
			return 'basic';
		case 2:
			return 'plus';
		case 3:
			return 'pro';
		default:
			return 'lite';
	}
}

/**
 * Get the setup wizard template name for the current plan tier.
 *
 * Maps all pro tiers (basic, plus, pro) to 'pro' template,
 * and lite to 'lite' template.
 *
 * @since 1.0.0
 *
 * @return string Either 'lite' or 'pro'.
 */
function get_rewardswp_setup_template(): string {
	$tier = get_rewardswp_plan_tier();

	// All pro tiers use the 'pro' template
	return $tier === 'lite' ? 'lite' : 'pro';
}

/**
 * Check if user has at least a certain plan level.
 *
 * @since 1.0.0
 *
 * @param string $required_plan The minimum required plan level.
 * @return bool Whether the user has the required plan level or higher.
 */
function has_rewardswp_plan_level( string $required_plan ): bool {
	$current_plan      = get_rewardswp_plan_tier();
	$current_priority  = get_plan_priority( $current_plan );
	$required_priority = get_plan_priority( $required_plan );

	return $current_priority >= $required_priority;
}

/**
 * Check if the current user can access a specific feature.
 *
 * This function validates feature access based on the user's plan tier
 * and caches the result for performance.
 *
 * @since 1.0.0
 *
 * @param string $feature The feature to check access for.
 * @return bool Whether the user can access the feature.
 */
function can_access_rewardswp_feature( string $feature ): bool {
	$service = am_rewardswp()->get_container()->get( FeatureGatingService::class );
	return $service->can_access( $feature );
}

/**
 * Get available features for the current plan.
 *
 * @since 1.0.0
 *
 * @return array Array of available feature names.
 */
function get_available_rewardswp_features(): array {
	$service = am_rewardswp()->get_container()->get( FeatureGatingService::class );
	return $service->get_available_features();
}

/**
 * Get the required plans for a feature.
 *
 * Returns an array of plan names that have access to the specified feature.
 * Excludes 'lite' from the result since Lite is the free version.
 *
 * @since 1.1.0
 *
 * @param string $feature The feature slug to check.
 * @return array Array of plan names (e.g., ['Plus', 'Pro']).
 */
function get_required_plans_for_feature( string $feature ): array {
	$service = am_rewardswp()->get_container()->get( FeatureGatingService::class );
	return $service->get_required_plans( $feature );
}

/**
 * Get the minimum required plan for a feature.
 *
 * Returns the lowest tier plan name that has access to the feature.
 *
 * @since 1.1.0
 *
 * @param string $feature The feature slug to check.
 * @return string The minimum required plan name (e.g., 'Plus'), or 'Pro' as fallback.
 */
function get_minimum_required_plan_for_feature( string $feature ): string {
	$service = am_rewardswp()->get_container()->get( FeatureGatingService::class );
	return $service->get_minimum_required_plan( $feature );
}

/**
 * Check if a plan tier is the highest available tier.
 *
 * @since 1.1.1
 *
 * @param string $plan Plan name to check.
 * @return bool True if this is the highest tier (Pro).
 */
function is_highest_plan_tier( string $plan ): bool {
	return strtolower( $plan ) === 'pro';
}

/**
 * Get the maximum number of redemption options allowed for Lite users.
 *
 * @since 1.1.1
 *
 * @return int Maximum redemption options for Lite plan.
 */
function get_lite_redemption_limit(): int {
	return 4;
}

/**
 * Get upgrade upsell data for a feature.
 *
 * Generates all common upgrade content (required_plan HTML, button_text,
 * button_url, compare_url) from a feature_slug. This centralizes the upgrade
 * upsell logic used by modals, drawers, and overlays.
 *
 * @since 1.1.1
 *
 * @param string $feature_slug Feature slug (e.g., 'points_expiry').
 * @param string $location     Location context for UTM tracking (e.g., 'settings', 'drawer').
 * @return array {
 *     @type string $min_plan      Minimum required plan name.
 *     @type string $required_plan HTML string showing "Required: Plan+ · Your plan: X".
 *     @type string $button_text   Button text "Upgrade to {Plan}".
 *     @type string $button_url    Full upgrade URL with UTM params.
 *     @type string $compare_url   Compare plans URL with UTM params.
 * }
 */
function get_upgrade_upsell_data( string $feature_slug, string $location = 'settings' ): array {
	$min_plan   = get_minimum_required_plan_for_feature( $feature_slug );
	$is_highest = is_highest_plan_tier( $min_plan );

	// Build "Required: Plan (or higher) · Your plan: X" - omit suffix if highest tier.
	$plan_suffix   = $is_highest ? '' : ' (or higher)';
	$required_plan = sprintf(
		'%s <span class="font-semibold text-gray-700">%s%s</span> · %s %s',
		esc_html__( 'Required:', 'rewardswp' ),
		esc_html( $min_plan ),
		$plan_suffix,
		esc_html__( 'Your plan:', 'rewardswp' ),
		esc_html( get_rewardswp_plan_tier_names()[ get_rewardswp_plan_tier() ] )
	);

	// Button text.
	$button_text = sprintf(
		/* translators: %s: Plan name */
		esc_html__( 'Upgrade to %s', 'rewardswp' ),
		esc_html( $min_plan )
	);

	// UTM content.
	$utm_content = 'upgrade_to_' . strtolower( str_replace( ' ', '_', $min_plan ) );

	// Button URL.
	$button_url = add_query_arg(
		'feature',
		$feature_slug,
		get_upgrade_url( $utm_content, $location, $min_plan, $feature_slug )
	);

	// Compare URL.
	$compare_url = add_query_arg(
		[
			'feature' => $feature_slug,
			'compare' => 'true',
		],
		get_upgrade_url( 'compare_plans', $location, $min_plan, $feature_slug )
	);

	return [
		'min_plan'      => $min_plan,
		'required_plan' => $required_plan,
		'button_text'   => $button_text,
		'button_url'    => $button_url,
		'compare_url'   => $compare_url,
	];
}

/**
 * Clear all feature access cache.
 *
 * This should be called when license status changes.
 *
 * @since 1.0.0
 */
function clear_rewardswp_feature_cache(): void {
	$service = am_rewardswp()->get_container()->get( FeatureGatingService::class );
	$service->clear_cache();
}
