<?php
/**
 * Base feature class for Dokan Kits features.
 *
 * @package DokanKits\Features
 * @since   3.0.0
 */

namespace DokanKits\Features;

use DokanKits\Core\Data\Models\Settings;
use DokanKits\Core\Data\Stores\SettingsDataStore;
use DokanKits\Core\Interfaces\Hookable;

/**
 * Abstract Feature
 *
 * Base class for all features in Dokan Kits.
 *
 * @since   3.0.0
 * @package DokanKits\Features
 */
abstract class Feature implements Featurable, Hookable {

	/**
	 * Feature option key
	 *
	 * @var string
	 */
	protected string $option_key = '';

	/**
	 * Feature settings group
	 *
	 * @var string
	 */
	protected string $settings_group = 'general';

	/**
	 * Feature settings section
	 *
	 * @var string
	 */
	protected string $settings_section = 'general';

	/**
	 * Available features
	 *
	 * @var int
	 */
	protected int $total_features = 0;

	/**
	 * Register hooks with WordPress
	 *
	 * This method must be implemented by all feature classes.
	 * It should register all necessary hooks for the feature to work.
	 *
	 * @return void
	 */
	abstract public function register_hooks(): void;

	/**
	 * Check if the feature is enabled
	 *
	 * @since 3.0.0
	 * @return bool
	 */
	public function is_enabled(): bool {
		// If option key is empty, feature is considered always enabled.
		if ( empty( $this->option_key ) ) {
			return apply_filters( 'dokan_kits_feature_' . $this->get_slug() . '_enabled', true, $this );
		}

		// Get the setting value and convert to boolean.
		$enabled = wc_string_to_bool( $this->get_setting( $this->option_key, false ) );

		return apply_filters( 'dokan_kits_feature_' . $this->get_slug() . '_enabled', $enabled, $this );
	}

	/**
	 * Get feature slug
	 *
	 * @since 3.0.0
	 * @return string
	 */
	public function get_slug(): string {
		$class_name = get_class( $this );
		$parts      = explode( '\\', $class_name );
		$last_part  = end( $parts );

		$slug = strtolower( preg_replace( '/(?<!^)[A-Z]/', '_$0', $last_part ) );

		return apply_filters( 'dokan_kits_feature_slug', $slug, $this, $class_name );
	}

	/**
	 * Get settings group
	 *
	 * @since 3.0.0
	 * @return string
	 */
	public function get_settings_group(): string {
		/**
		 * Filter the settings group for a feature.
		 *
		 * @since 3.0.0
		 *
		 * @param string  $settings_group The settings group.
		 * @param Feature $feature        Current feature instance.
		 */
		return apply_filters( "dokan_kits_feature_{$this->get_slug()}_settings_group", $this->settings_group, $this );
	}

	/**
	 * Get settings section
	 *
	 * @since 3.0.0
	 * @return string
	 */
	public function get_settings_section(): string {
		/**
		 * Filter the settings section for a feature.
		 *
		 * @since 3.0.0
		 *
		 * @param string  $settings_section The settings section.
		 * @param Feature $feature          Current feature instance.
		 */
		return apply_filters( "dokan_kits_feature_{$this->get_slug()}_settings_section", $this->settings_section, $this );
	}

	/**
	 * Get available features
	 *
	 * @since 3.0.0
	 * @return int
	 */
	public function get_total_features(): int {
		/**
		 * Filter the total number of features.
		 *
		 * @since 3.0.0
		 *
		 * @param int     $total_features Total number of features.
		 * @param Feature $feature        Current feature instance.
		 */
		return apply_filters( "dokan_kits_feature_{$this->get_slug()}_total_features", $this->total_features, $this );
	}

	/**
	 * Get active feature count
	 *
	 * Returns the number of active features within this feature class.
	 * For CartButtons, this checks if the main feature is enabled.
	 *
	 * @since 3.0.0
	 * @return int
	 */
	public function get_active_features_count(): int {
		$count = (int) $this->is_enabled();

		/**
		 * Filter the active features count.
		 *
		 * @since 3.0.0
		 *
		 * @param int     $count   Active features count.
		 * @param Feature $feature Current feature instance.
		 */
		return apply_filters( "dokan_kits_feature_{$this->get_slug()}_active_features_count", $count, $this );
	}

	/**
	 * Get setting by key
	 *
	 * @since 3.0.0
	 *
	 * @param string $key           Setting key.
	 * @param mixed  $default_value Default value.
	 *
	 * @return mixed
	 */
	public function get_setting( string $key, $default_value = '' ) {
		// Get the setting using the data store.
		$settings_store = dokan_kits_get_container()->get( SettingsDataStore::class );
		$setting        = $settings_store->get_settings_by_name( $this->get_settings_group() );

		if ( $setting instanceof Settings ) {
			$data  = $setting->get_value() ?? array();
			$value = $data[ $this->get_settings_section() ][ $key ] ?? $default_value;
		} else {
			$value = $default_value;
		}

		/**
		 * Filter a feature setting value.
		 *
		 * @since 3.0.0
		 *
		 * @param mixed   $value         Setting value.
		 * @param string  $key           Setting key.
		 * @param mixed   $default_value Default value.
		 * @param Feature $feature       Current feature instance.
		 */
		return apply_filters( "dokan_kits_feature_{$this->get_slug()}_setting", $value, $key, $default_value, $this );
	}
}
