<?php
/**
 * Arquitectura extensible para copias de seguridad automáticas.
 *
 * Los proveedores concretos (archivo, S3, cron externo) se registran sin
 * acoplar el núcleo del plugin al mecanismo de respaldo.
 *
 * @package Logistica
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Registro y orquestación de proveedores de backup.
 */
class Logistica_Backup {

	/**
	 * @var array<string, callable>
	 */
	private static $providers = array();

	/**
	 * @param string   $key      Identificador del proveedor.
	 * @param callable $callback Función que ejecuta el backup y devuelve true|WP_Error.
	 * @return void
	 */
	public static function register_provider( $key, $callback ) {
		$key = sanitize_key( (string) $key );
		if ( '' === $key || ! is_callable( $callback ) ) {
			return;
		}

		self::$providers[ $key ] = $callback;
	}

	/**
	 * @return array<string, callable>
	 */
	public static function providers() {
		return self::$providers;
	}

	/**
	 * Ejecuta todos los proveedores registrados (hook programable).
	 *
	 * @param array<string, mixed> $context Metadatos opcionales (trigger, scope, etc.).
	 * @return array<string, true|WP_Error>
	 */
	public static function run_all( $context = array() ) {
		$results = array();

		foreach ( self::$providers as $key => $callback ) {
			/**
			 * Permite omitir proveedores según contexto.
			 *
			 * @param bool                 $run     Si ejecutar.
			 * @param string               $key     Proveedor.
			 * @param array<string, mixed> $context Contexto.
			 */
			$run = apply_filters( 'logistica_backup_should_run_provider', true, $key, $context );
			if ( ! $run ) {
				continue;
			}

			$result          = call_user_func( $callback, $context );
			$results[ $key ] = is_wp_error( $result ) ? $result : true;
		}

		/**
		 * Notifica resultado agregado de backups.
		 *
		 * @param array<string, true|WP_Error> $results Resultados por proveedor.
		 * @param array<string, mixed>         $context Contexto.
		 */
		do_action( 'logistica_backup_completed', $results, $context );

		return $results;
	}

	/**
	 * Programa el evento cron del plugin (stub listo para cron real).
	 *
	 * @return void
	 */
	public static function schedule_events() {
		if ( ! wp_next_scheduled( 'logistica_backup_cron' ) ) {
			wp_schedule_event( time() + HOUR_IN_SECONDS, 'daily', 'logistica_backup_cron' );
		}
	}

	/**
	 * @return void
	 */
	public static function init() {
		add_action( 'logistica_backup_cron', array( __CLASS__, 'run_scheduled' ) );

		/**
		 * Punto de extensión para registrar proveedores desde otro código.
		 */
		do_action( 'logistica_backup_register_providers' );
	}

	/**
	 * @return void
	 */
	public static function run_scheduled() {
		self::run_all(
			array(
				'trigger' => 'cron',
				'scope'   => 'full',
			)
		);
	}
}
