<?php
/**
 * Module-selected database table ownership resolver.
 *
 * @package ScheduledChanges
 */

namespace ScheduledChanges\Database;

// phpcs:disable WordPress.Security.EscapeOutput.ExceptionNotEscaped -- Exception messages are escaped at UI boundaries.

use ScheduledChanges\Extension\ModuleDefinition;
use ScheduledChanges\Extension\ModuleRegistry;

/**
 * Resolves database tables owned by the selected module graph.
 */
final class ModuleTableSelector {
	private ModuleRegistry $registry;
	private TableNames $tables;
	private string $profile;

	/**
	 * Creates the table selector.
	 *
	 * @param ModuleRegistry|null $registry Module registry.
	 * @param TableNames|null     $tables Table resolver.
	 * @param string              $profile Module distribution profile.
	 */
	public function __construct( ?ModuleRegistry $registry = null, ?TableNames $tables = null, string $profile = '' ) {
		$this->registry = $registry ?? new ModuleRegistry();
		$this->tables   = $tables ?? new TableNames();
		$this->profile  = $profile;
	}

	/**
	 * Returns concrete table names owned by the selected module graph.
	 *
	 * @return array<string,string>
	 */
	public function selectedTables(): array {
		$available = $this->tables->all();
		$selected  = array();

		$report = $this->registry->catalogReport( $this->profile );
		if ( ! $report->healthy() ) {
			throw new \RuntimeException( 'Cannot resolve module tables from an unhealthy module graph: ' . implode( '; ', $report->errors() ) );
		}

		foreach ( $report->definitions() as $definition ) {
			foreach ( $definition->resourceOwnership()[ ModuleDefinition::RESOURCE_TABLE ] ?? array() as $table_key ) {
				if ( isset( $available[ $table_key ] ) ) {
					$selected[ $table_key ] = $available[ $table_key ];
				}
			}
		}

		ksort( $selected );

		return $selected;
	}
}
