<?php

namespace SugarCalendarBookings\Integrations\CalendarEvents;

use SugarCalendarBookings\Integrations\OAuthRelay\OAuthConnectionModel;

/**
 * Immutable snapshot of deliverable connections per calendar event provider.
 *
 * Built by DeliverableConnectionResolver. Consumed by EventLinkDiffer.
 *
 * @since 1.5.0
 */
class DeliverableConnectionMap {

	/**
	 * Connections keyed by provider slug.
	 *
	 * @since 1.5.0
	 *
	 * @var array<string, OAuthConnectionModel[]>
	 */
	private array $connections_by_slug;

	/**
	 * Constructor.
	 *
	 * @since 1.5.0
	 *
	 * @param array<string, OAuthConnectionModel[]> $connections_by_slug Connections keyed by provider slug.
	 */
	public function __construct( array $connections_by_slug ) {

		$normalized = [];

		foreach ( $connections_by_slug as $slug => $connections ) {

			if ( ! is_string( $slug ) || $slug === '' || ! is_array( $connections ) ) {
				continue;
			}

			$normalized[ $slug ] = array_values(
				array_filter(
					$connections,
					static fn( $connection ) => $connection instanceof OAuthConnectionModel
				)
			);
		}

		$this->connections_by_slug = $normalized;
	}

	/**
	 * Build an empty map.
	 *
	 * @since 1.5.0
	 *
	 * @return self
	 */
	public static function empty(): self {

		return new self( [] );
	}

	/**
	 * Get the deliverable connections for the given provider slug.
	 *
	 * @since 1.5.0
	 *
	 * @param string $slug Provider slug.
	 *
	 * @return OAuthConnectionModel[]
	 */
	public function for_provider( string $slug ): array {

		return $this->connections_by_slug[ $slug ] ?? [];
	}

	/**
	 * Check whether the given connection is deliverable for the given provider slug.
	 *
	 * @since 1.5.0
	 *
	 * @param string               $slug       Provider slug.
	 * @param OAuthConnectionModel $connection Connection to check.
	 *
	 * @return bool
	 */
	public function contains( string $slug, OAuthConnectionModel $connection ): bool {

		foreach ( $this->for_provider( $slug ) as $candidate ) {

			if ( (int) $candidate->id === (int) $connection->id ) {
				return true;
			}
		}

		return false;
	}

	/**
	 * Get all provider slugs in the map.
	 *
	 * @since 1.5.0
	 *
	 * @return string[]
	 */
	public function provider_slugs(): array {

		return array_keys( $this->connections_by_slug );
	}

	/**
	 * Whether the map has no providers with deliverable connections.
	 *
	 * @since 1.5.0
	 *
	 * @return bool
	 */
	public function is_empty(): bool {

		foreach ( $this->connections_by_slug as $connections ) {

			if ( $connections !== [] ) {
				return false;
			}
		}

		return true;
	}
}
