<?php

namespace WeDevs\AppBridge\Core\Notifications;

use InvalidArgumentException;
use WeDevs\AppBridge\Core\Notifications\Contracts\NotificationDriverInterface;
use WeDevs\AppBridge\Core\Notifications\Drivers\OneSignalDriver;

class NotificationDriverFactory {

	/**
	 * Default option key used when no integration-specific key is supplied.
	 * Matches the legacy WooCommerce / Pocket Store option for back-compat.
	 */
	public const DEFAULT_OPTION_KEY = 'app_bridge_notification_settings';

	/**
	 * Resolve a driver instance by name.
	 *
	 * Currently only OneSignal ships in-tree. Third parties can register
	 * additional drivers via the `app_bridge_notification_drivers` filter —
	 * return `[ 'driver_name' => callable( string $option_key ): NotificationDriverInterface ]`.
	 *
	 * @param string $driver     Driver name (e.g. 'onesignal').
	 * @param string $option_key Option key whose `onesignal` / `notification_provider`
	 *                           subarray supplies the credentials. Each integration
	 *                           owns its own credentials, so callers in the manual
	 *                           Send-Notifications panel and runtime event dispatcher
	 *                           must pass the integration's option key.
	 */
	public static function make( string $driver, string $option_key = self::DEFAULT_OPTION_KEY ): NotificationDriverInterface {
		$factories = apply_filters(
			'app_bridge_notification_drivers',
			[
				'onesignal' => [ self::class, 'make_onesignal' ],
			]
		);

		if ( ! isset( $factories[ $driver ] ) || ! is_callable( $factories[ $driver ] ) ) {
			throw new InvalidArgumentException(
				sprintf( 'Unsupported notification driver "%s".', esc_html( $driver ) )
			);
		}

		$instance = call_user_func( $factories[ $driver ], $option_key );

		if ( ! $instance instanceof NotificationDriverInterface ) {
			throw new InvalidArgumentException(
				sprintf( 'Driver "%s" did not return a NotificationDriverInterface instance.', esc_html( $driver ) )
			);
		}

		return $instance;
	}

	public static function make_onesignal( string $option_key = self::DEFAULT_OPTION_KEY ): OneSignalDriver {
		$settings = self::settings( $option_key )['onesignal'] ?? [];

		return new OneSignalDriver(
			(string) ( $settings['app_id'] ?? '' ),
			(string) ( $settings['rest_api_key'] ?? '' )
		);
	}

	/**
	 * Driver names to dispatch through when the caller (or event definition)
	 * doesn't pin a specific list. Mirrors the provider chosen in the given
	 * integration's Push Notifications → Configuration → Provider setting.
	 *
	 * @return string[]
	 */
	public static function selected_drivers( string $option_key = self::DEFAULT_OPTION_KEY ): array {
		$selected = (string) ( self::settings( $option_key )['notification_provider'] ?? 'onesignal' );

		/**
		 * Filter the default driver list used for event dispatch.
		 *
		 * @param string[] $drivers    Driver names.
		 * @param string   $selected   The provider currently chosen in settings.
		 * @param string   $option_key The option key the settings were read from.
		 */
		return apply_filters( 'app_bridge_default_notification_drivers', [ $selected ], $selected, $option_key );
	}

	/**
	 * @return array<string, mixed>
	 */
	private static function settings( string $option_key ): array {
		return (array) get_option( $option_key, [] );
	}
}
