<?php
/**
 * Default provider authorization policy.
 *
 * @package ScheduledChanges
 */

namespace ScheduledChanges\Provider;

use ScheduledChanges\Capabilities\WordPressPermissionService;
use ScheduledChanges\Domain\Operation\TargetDefinition;
use ScheduledChanges\Extension\PublicHooks;

/**
 * Fails closed for non-native provider-owned targets unless an extension opts in.
 */
final class ProviderAuthorizationService implements ProviderAuthorization {
	private const NATIVE_PROVIDER = 'wordpress-core';

	private WordPressPermissionService $permissions;

	/** Creates the authorization service. */
	public function __construct( ?WordPressPermissionService $permissions = null ) {
		$this->permissions = $permissions ?? new WordPressPermissionService();
	}

	public function canInspect( int $actor_id, TargetDefinition $target ): bool {
		return $this->authorize( self::ACTION_INSPECT, $actor_id, $target );
	}

	public function canSchedule( int $actor_id, TargetDefinition $target ): bool {
		return $this->authorize( self::ACTION_SCHEDULE, $actor_id, $target );
	}

	public function canExecute( int $actor_id, TargetDefinition $target ): bool {
		return $this->authorize( self::ACTION_EXECUTE, $actor_id, $target );
	}

	public function canRollback( int $actor_id, TargetDefinition $target ): bool {
		return $this->authorize( self::ACTION_ROLLBACK, $actor_id, $target );
	}

	public function canDelete( int $actor_id, TargetDefinition $target ): bool {
		return $this->authorize( self::ACTION_DELETE, $actor_id, $target );
	}

	/**
	 * Applies core native policy and extension-owned authorization filters.
	 */
	private function authorize( string $action, int $actor_id, TargetDefinition $target ): bool {
		try {
			$authorized = self::NATIVE_PROVIDER === $target->providerId()
				? $this->nativeAuthorization( $action, $actor_id, $target )
				: false;

			return PublicHooks::providerAuthorization( $authorized, $action, $actor_id, $target );
		} catch ( \RuntimeException $exception ) {
			unset( $exception );

			return false;
		}
	}

	/**
	 * Authorizes core-owned native WordPress targets.
	 */
	private function nativeAuthorization( string $action, int $actor_id, TargetDefinition $target ): bool {
		if ( self::ACTION_INSPECT === $action ) {
			return $this->permissions->canInspectTarget( $actor_id, $target );
		}

		if ( self::ACTION_DELETE === $action ) {
			return $this->permissions->actorCan( $actor_id, 'delete_post', $target );
		}

		if ( in_array( $action, array( self::ACTION_SCHEDULE, self::ACTION_EXECUTE, self::ACTION_ROLLBACK ), true ) ) {
			return $this->permissions->actorCan( $actor_id, 'edit_post', $target );
		}

		return false;
	}
}
