<?php
/** Free and paid Companion access boundaries. */

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

/**
 * Complete, useful Free surface. It deliberately contains no raw file, database,
 * user, plugin, theme, order, form-entry, live-editor or provider-write access.
 *
 * @return string[]
 */
function wpagent_companion_free_ability_names(): array {
	return array(
		'wp-agent/create-post-from-markdown',
		'wp-agent/get-post',
		'wp-agent/list-posts',
		'wp-agent/update-post',
		'wp-agent/set-post-status',
		'wp-agent/trash-post',
		'wp-agent/restore-post',
		'wp-agent/create-term',
		'wp-agent/update-term',
		'wp-agent/get-term',
		'wp-agent/list-terms',
		'wp-agent/set-post-terms',
		'wp-agent/upload-media',
		'wp-agent/set-alt-text',
		'wp-agent/set-featured-image',
		'wp-agent/list-media',
		'wp-agent/list-comments',
		'wp-agent/moderate-comment',
		'wp-agent/reply-to-comment',
		'wp-agent/get-seo-meta',
		'wp-agent/set-seo-meta',
		'wp-agent/render-check',
		'wp-agent/render-verify',
		'wp-agent/refresh-hooks',
		'wp-agent/detect-builder',
		'wp-agent/get-builder-compatibility',
		'wp-agent/list-block-types',
		'wp-agent/get-block-type',
		'wp-agent/get-native-block-document',
		'wp-agent/get-site-context',
		'wp-agent/update-site-context',
		'wp-agent/get-system-diagnostics',
		'wp-agent/list-skills',
		'wp-agent/get-skill',
	);
}

/** The paid tier is proven only by the existing Polar proof or explicit dev bypass. */
function wpagent_companion_access_tier(): string {
	return function_exists( 'wpagent_companion_license_is_valid' ) && wpagent_companion_license_is_valid()
		? 'paid'
		: 'free';
}

function wpagent_companion_ability_entitled( string $name ): bool {
	return 'paid' === wpagent_companion_access_tier()
		|| in_array( $name, wpagent_companion_free_ability_names(), true );
}

/**
 * Keep paid-only disable choices dormant while Free is active.
 *
 * Saving the Free controls must not erase a customer's paid configuration.
 * A later licence renewal therefore cannot silently re-enable abilities that
 * the administrator had explicitly disabled before the licence interruption.
 *
 * @param string[]                            $submitted Ability names submitted by the visible controls.
 * @param string[]                            $existing  Previously disabled ability names.
 * @param array<string,array<string,mixed>>   $catalog   Current Companion catalog.
 * @param bool                                $paid      Whether paid controls are currently available.
 * @return string[]
 */
function wpagent_companion_merge_disabled_abilities_for_tier( array $submitted, array $existing, array $catalog, bool $paid ): array {
	$free = array_flip( wpagent_companion_free_ability_names() );
	$submitted_disabled = array_values(
		array_filter(
			$submitted,
			static fn( $name ): bool => is_string( $name )
				&& isset( $catalog[ $name ] )
				&& ( $paid || isset( $free[ $name ] ) )
		)
	);
	if ( $paid ) {
		return array_values( array_unique( $submitted_disabled ) );
	}

	$paid_only_disabled = array_values(
		array_filter(
			$existing,
			static fn( $name ): bool => is_string( $name )
				&& isset( $catalog[ $name ] )
				&& ! isset( $free[ $name ] )
		)
	);
	return array_values( array_unique( array_merge( $paid_only_disabled, $submitted_disabled ) ) );
}
