<?php

namespace WeDevs\AppBridge\Core\Notifications;

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

/**
 * A concrete Notification carrying an event from the EVENTS.MD catalog.
 *
 * The wire payload mirrors EVENTS.MD exactly:
 *   title, body, notification_channel_id, screen_route, data
 *
 * Drivers translate that single shape into their own transport format.
 */
class Event extends Notification implements OneSignalMessage {

	private string $key;
	private string $title;
	private string $body;
	private string $channel_id;
	private string $screen_route;

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

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

	/** @var array<string, mixed> Audience hints — see EventDispatcher::dispatch(). */
	private array $audience;

	private string $option_key;

	/**
	 * @param array<string, mixed> $data
	 * @param string[]             $via      Empty = use the provider currently selected in settings.
	 * @param array<string, mixed> $audience
	 */
	public function __construct(
		string $key,
		string $title,
		string $body,
		string $channel_id,
		string $screen_route,
		array $data = [],
		array $via = [],
		array $audience = [],
		string $option_key = NotificationDriverFactory::DEFAULT_OPTION_KEY
	) {
		$this->key          = $key;
		$this->title        = $title;
		$this->body         = $body;
		$this->channel_id   = $channel_id;
		$this->screen_route = $screen_route;
		$this->data         = $data;
		$this->via          = $via;
		$this->audience     = $audience;
		$this->option_key   = $option_key;
	}

	public function key(): string {
		return $this->key;
	}

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

	/**
	 * @return array<string, mixed>
	 */
	public function audience(): array {
		return $this->audience;
	}

	public function to_array(): array {
		return [
			'title'                   => $this->title,
			'body'                    => $this->body,
			'notification_channel_id' => $this->channel_id,
			'screen_route'            => $this->screen_route,
			'data'                    => $this->data,
		];
	}

	public function to_onesignal(): array {
		$payload = [
			'title'   => $this->title,
			'message' => $this->body,
			'data'    => array_merge(
				$this->data,
				[
					'event'                   => $this->key,
					'notification_channel_id' => $this->channel_id,
					'screen_route'            => $this->screen_route,
				]
			),
		];

		// Mirror the legacy payload routing fields when the dispatcher's context
		// supplies them — keeps existing mobile clients (which key off
		// data.action_type / data.action_type_id) working without changes.
		if ( ! empty( $this->data['action_type'] ) ) {
			$payload['action_type'] = (string) $this->data['action_type'];
		} else {
			$payload['action_type'] = $this->channel_id;
		}

		if ( ! empty( $this->data['action_type_id'] ) ) {
			$payload['action_type_id'] = (string) $this->data['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['player_ids'] ) ) {
			$payload['include_player_ids'] = (array) $this->audience['player_ids'];
		} elseif ( ! empty( $this->audience['segments'] ) ) {
			$payload['included_segments'] = (array) $this->audience['segments'];
		}

		return $payload;
	}
}
