<?php

namespace WeDevs\AppBridge\Core\Notifications\Messages;

use WeDevs\AppBridge\Core\Notifications\Contracts\OneSignalMessage;
use WeDevs\AppBridge\Core\Notifications\Notification;
use WeDevs\AppBridge\Core\Notifications\NotificationDriverFactory;

/**
 * Ad-hoc admin-triggered push (the "Send Notifications" form).
 *
 * Mirrors the legacy {@see \WeDevs\AppBridge\Integrations\Dokan\REST\PushNotificationController}
 * input contract: title + message, optional icon, action_type, action_type_id —
 * extended with caller-supplied audience targeting.
 *
 * Audience shape:
 *   [
 *     'external_user_ids' => [ '12', '34' ],   // OneSignal external IDs (= WP user IDs)
 *     'roles'             => [ 'vendor', 'customer' ], // OneSignal tag filter on `wp_role`
 *   ]
 *
 * Extras shape (all optional):
 *   [
 *     'icon'           => 'https://…',         // → large_icon
 *     'action_type'    => 'category',          // → data.action_type
 *     'action_type_id' => '123',               // → data.action_type_id
 *   ]
 */
class BroadcastNotification extends Notification implements OneSignalMessage {

	private string $title;
	private string $message;

	/** @var array<string, mixed> */
	private array $audience;

	/** @var array<string, mixed> */
	private array $extras;

	/** @var string[] */
	private array $via;

	private string $option_key;

	/**
	 * @param array<string, mixed> $audience
	 * @param array<string, mixed> $extras   icon, action_type, action_type_id
	 * @param string[]             $via      empty = use the provider selected in settings
	 */
	public function __construct(
		string $title,
		string $message,
		array $audience = [],
		array $extras = [],
		array $via = [],
		string $option_key = NotificationDriverFactory::DEFAULT_OPTION_KEY
	) {
		$this->title      = $title;
		$this->message    = $message;
		$this->audience   = $audience;
		$this->extras     = $extras;
		$this->via        = $via;
		$this->option_key = $option_key;
	}

	public function via(): array {
		return ! empty( $this->via ) ? $this->via : NotificationDriverFactory::selected_drivers( $this->option_key );
	}

	public function to_onesignal(): array {
		$payload = [
			'title'   => $this->title,
			'message' => $this->message,
		];

		if ( ! empty( $this->extras['icon'] ) ) {
			$payload['icon'] = (string) $this->extras['icon'];
		}
		if ( ! empty( $this->extras['action_type'] ) ) {
			$payload['action_type'] = (string) $this->extras['action_type'];
		}
		if ( ! empty( $this->extras['action_type_id'] ) ) {
			$payload['action_type_id'] = (string) $this->extras['action_type_id'];
		}

		if ( ! empty( $this->audience['external_user_ids'] ) ) {
			$payload['include_external_user_ids'] = array_map( 'strval', (array) $this->audience['external_user_ids'] );
		} elseif ( ! empty( $this->audience['roles'] ) ) {
			$payload['filters'] = self::role_filters( (array) $this->audience['roles'] );
		}

		return $payload;
	}

	/**
	 * Build OneSignal `filters` array OR'd across the role list.
	 *
	 * @param string[] $roles
	 * @return array<int, array<string, string>>
	 */
	private static function role_filters( array $roles ): array {
		$filters = [];
		$first   = true;

		foreach ( $roles as $role ) {
			if ( ! $first ) {
				$filters[] = [ 'operator' => 'OR' ];
			}
			$filters[] = [
				'field'    => 'tag',
				'key'      => 'wp_role',
				'relation' => '=',
				'value'    => (string) $role,
			];
			$first = false;
		}

		return $filters;
	}
}
