<?php
/**
 * Pro/free feature gating for AI Alt Text.
 *
 * Guideline 5/6: Lite must not ship a feature and lock it. Premium
 * implementations live in overlay files. This class only reports whether
 * those files plus a license are present. Usage cutoffs are not applied
 * to the wordpress.org Lite edition.
 *
 * @package AIAltTextGenerator
 * @since 1.9.0
 */

namespace AIAltTextGenerator;

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

/**
 * @since 1.9.0
 */
class FeatureGate {

	public const FREE_MONTHLY_LIMIT = 50;

	/** @var list<string> */
	public const FREE_OPENAI_MODELS = [
		'gpt-4o-mini',
		'gpt-4.1-nano',
	];

	/** @var list<string> */
	private const PRO_FEATURES = [
		'gemini',
		'claude',
		'scheduled_scan',
		'email_reports',
		'full_content_scan',
		'csv_import',
		'bulk_duplicates',
		'premium_models',
		'custom_monthly_limit',
	];

	public static function isPro(): bool {
		$unlocked = function_exists( 'wp_powersuite_is_license_valid' ) && wp_powersuite_is_license_valid();

		/**
		 * Filter whether AI Alt Text pro features are unlocked.
		 *
		 * @param bool $unlocked Whether the Pro overlay is licensed.
		 */
		return (bool) apply_filters( 'wpps_ai_alt_text_is_pro', $unlocked );
	}

	public static function featureEnabled( string $feature ): bool {
		if ( ! in_array( $feature, self::PRO_FEATURES, true ) ) {
			return true;
		}

		return self::isPro();
	}

	public static function isProviderAllowed( string $provider ): bool {
		$provider = Settings::sanitizeProvider( $provider );

		if ( $provider === 'openai' ) {
			return true;
		}

		$class = match ( $provider ) {
			'gemini' => \AIAltTextGenerator\Providers\GeminiProvider::class,
			'claude' => \AIAltTextGenerator\Providers\ClaudeProvider::class,
			default  => '',
		};

		return $class !== '' && class_exists( $class, false ) && self::isPro();
	}

	public static function isOpenAiModelAllowed( string $model ): bool {
		$model = trim( sanitize_text_field( $model ) );
		if ( $model === '' ) {
			return false;
		}

		return array_key_exists( $model, Models::getList() );
	}

	/**
	 * @param array<string, mixed> $settings
	 */
	public static function effectiveMonthlyLimit( array $settings ): int {
		if ( self::isPro() ) {
			$limit = (int) ( $settings['monthly_limit'] ?? 0 );

			return $limit > 0 ? $limit : 0;
		}

		if ( function_exists( 'wp_powersuite_is_lite_edition' ) && wp_powersuite_is_lite_edition() ) {
			return 0;
		}

		return self::FREE_MONTHLY_LIMIT;
	}

	public static function shouldHideCosts(): bool {
		$settings = Settings::get();

		return ! empty( $settings['client_safe_mode'] );
	}

	/**
	 * Clamp settings for the active tier at runtime.
	 *
	 * @param array<string, mixed> $settings
	 * @return array<string, mixed>
	 */
	public static function applyTierLimits( array $settings ): array {
		if ( self::isPro() ) {
			return $settings;
		}

		if ( ! self::isProviderAllowed( (string) ( $settings['provider'] ?? 'openai' ) ) ) {
			$settings['provider'] = 'openai';
			$settings['model']    = Models::DEFAULT;
		}

		$settings['model'] = Models::sanitize( (string) ( $settings['model'] ?? Models::DEFAULT ), $settings );
		if ( ! self::isOpenAiModelAllowed( (string) $settings['model'] ) ) {
			$settings['model'] = Models::DEFAULT;
		}

		if ( ! self::featureEnabled( 'scheduled_scan' ) ) {
			$settings['scan_schedule'] = 'manual';
			$settings['email_reports'] = false;
		}

		$settings['monthly_limit'] = 0;

		return $settings;
	}

	/**
	 * Preserve premium-only settings on save when license is inactive.
	 *
	 * @param array<string, mixed> $settings Sanitized settings about to be saved.
	 * @param array<string, mixed> $existing Previously stored settings.
	 * @return array<string, mixed>
	 */
	public static function preservePremiumSettingsOnSave( array $settings, array $existing ): array {
		if ( self::isPro() ) {
			return $settings;
		}

		$existing_provider = Settings::sanitizeProvider( (string) ( $existing['provider'] ?? 'openai' ) );
		if ( ! self::isProviderAllowed( (string) ( $settings['provider'] ?? 'openai' ) ) ) {
			$settings['provider'] = self::isProviderAllowed( $existing_provider ) ? $existing_provider : 'openai';
		}

		$model = Models::sanitize( (string) ( $settings['model'] ?? Models::DEFAULT ), $settings );
		if ( ! self::isOpenAiModelAllowed( $model ) ) {
			$existing_model = Models::sanitize( (string) ( $existing['model'] ?? Models::DEFAULT ), $settings );
			$settings['model'] = self::isOpenAiModelAllowed( $existing_model ) ? $existing_model : Models::DEFAULT;
		}

		$existing_schedule = (string) ( $existing['scan_schedule'] ?? 'manual' );
		if ( ! self::featureEnabled( 'scheduled_scan' ) ) {
			$settings['scan_schedule'] = in_array( $existing_schedule, [ 'daily', 'weekly', 'monthly' ], true )
				? $existing_schedule
				: 'manual';
			$settings['email_reports'] = ! empty( $existing['email_reports'] );
		}

		$settings['monthly_limit'] = 0;

		return $settings;
	}
}
