<?php
/**
 * Module resource resolver.
 *
 * @package ScheduledChanges
 */

namespace ScheduledChanges\Extension;

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

/**
 * Resolves owned resources in dependency-safe lifecycle order.
 */
final class ModuleResourceSelector {
	private ModuleRegistry $registry;
	private string $profile;

	public function __construct( ?ModuleRegistry $registry = null, string $profile = '' ) {
		$this->registry = $registry ?? new ModuleRegistry();
		$this->profile  = $profile;
	}

	/**
	 * Returns selected definitions in dependency-first lifecycle order.
	 *
	 * @return ModuleDefinition[]
	 */
	public function definitions(): array {
		$report = $this->registry->catalogReport( $this->profile );

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

		return $report->definitions();
	}

	/**
	 * Returns selected definitions in dependent-first uninstall order.
	 *
	 * @return ModuleDefinition[]
	 */
	public function uninstallDefinitions(): array {
		return array_reverse( $this->definitions() );
	}

	/**
	 * Returns unique selected resources of one kind in lifecycle order.
	 *
	 * @return string[]
	 */
	public function resources( string $kind, bool $uninstall_order = false ): array {
		$definitions = $uninstall_order ? $this->uninstallDefinitions() : $this->definitions();
		$resources   = array();

		foreach ( $definitions as $definition ) {
			foreach ( $definition->resourceOwnership()[ $kind ] ?? array() as $resource ) {
				$resources[] = (string) $resource;
			}
		}

		return array_values( array_unique( $resources ) );
	}

	/**
	 * Returns resources keyed by owner in lifecycle order.
	 *
	 * @return array<string,string[]>
	 */
	public function resourcesByModule( string $kind, bool $uninstall_order = false ): array {
		$definitions = $uninstall_order ? $this->uninstallDefinitions() : $this->definitions();
		$resources   = array();

		foreach ( $definitions as $definition ) {
			$owned = $definition->resourceOwnership()[ $kind ] ?? array();
			if ( array() !== $owned ) {
				$resources[ $definition->slug() ] = array_values( $owned );
			}
		}

		return $resources;
	}
}
