<?php
/**
 * Scheduled task orchestration for admin autonomy runtime.
 *
 * @package Niwa_AI
 */

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

class Niwa_AI_Admin_Autonomy_Scheduled_Task_Runner {
	/** @var object|null */
	private $chat_agent;

	/** @var array<string,callable> */
	private $callbacks;

	public function __construct( $chat_agent = null, $callbacks = array() ) {
		$this->chat_agent = $chat_agent;
		$this->callbacks  = is_array( $callbacks ) ? $callbacks : array();
	}

	public function run( $limit = 3 ) {
		// Founder messages always get the first execution slot. Background
		// maintenance must never make an already queued conversation wait.
		$actors          = $this->call( 'process_actor_runtime', array( $limit ), array( 'success' => true ) );
		$scheduled       = $this->call( 'process_due_scheduled_jobs', array( $limit ), array( 'success' => true, 'processed' => 0 ) );
		$daily           = $this->call_chat_agent( 'maybe_send_daily_report' );
		$workspace       = $this->call_chat_agent( 'maybe_send_workspace_heartbeat' );
		$operative       = $this->call_chat_agent( 'maybe_run_operative_heartbeat' );
		$stock_operative = $this->call_chat_agent( 'maybe_run_stock_manager_operative_heartbeat' );
		$post_memory     = $this->call( 'process_post_reply_memory', array( 5 ), array( 'success' => true, 'processed' => 0 ) );
		$companion       = $this->call_chat_agent( 'companion_distillation_tick' );

		$errors = array();
		foreach ( array( $scheduled, $daily, $workspace, $operative, $stock_operative, $actors, $post_memory, $companion ) as $result ) {
			$this->collect_errors( $errors, $result );
		}

		return array(
			'success'                 => empty( $errors ),
			'processed'               => intval( isset( $scheduled['processed'] ) ? $scheduled['processed'] : 0 ),
			'daily_report'            => is_array( $daily ) ? $daily : array( 'success' => true ),
			'workspace_heartbeat'     => is_array( $workspace ) ? $workspace : array( 'success' => true ),
			'operative_heartbeat'     => is_array( $operative ) ? $operative : array( 'success' => true ),
			'stock_manager_heartbeat' => is_array( $stock_operative ) ? $stock_operative : array( 'success' => true ),
			'actor_sessions'          => intval( isset( $actors['processed_sessions'] ) ? $actors['processed_sessions'] : 0 ),
			'actor_messages'          => intval( isset( $actors['processed_messages'] ) ? $actors['processed_messages'] : 0 ),
			'has_pending_actors'      => ! empty( $actors['pending'] ),
			'post_reply_memory'       => is_array( $post_memory ) ? $post_memory : array( 'success' => true ),
			'companion_distillation'  => is_array( $companion ) ? $companion : array( 'success' => true ),
			'errors'                  => $errors,
		);
	}

	private function call_chat_agent( $method ) {
		if ( $this->chat_agent && method_exists( $this->chat_agent, $method ) ) {
			return $this->chat_agent->{$method}();
		}

		return array( 'success' => true );
	}

	private function collect_errors( &$errors, $result ) {
		if ( ! is_array( $result ) ) {
			return;
		}
		if ( ! empty( $result['error'] ) ) {
			$errors[] = (string) $result['error'];
		}
		if ( ! empty( $result['errors'] ) && is_array( $result['errors'] ) ) {
			$errors = array_merge( $errors, array_values( array_filter( $result['errors'] ) ) );
		}
	}

	private function call( $name, $args = array(), $default = null ) {
		return Niwa_AI_Admin_Autonomy_Callbacks::call( $this->callbacks, $name, $args, $default );
	}
}
