<?php
/**
 * Progress Event Class.
 *
 * Represents a progress update event for long-running operations. This is a
 * system-wide event visible to all connected users. The operation identifier
 * identifies the type of process that the progress event is for.
 *
 * @package   Agenistrator
 * @since     1.0.0
 * @author    Alex Ruban <alex@maximum.guru>
 * @author    Maximum Software Inc <contact@maximum.software>
 * @license   GPL-3.0-only
 * @link      https://agenistrator.com/
 *
 * SPDX-FileCopyrightText: 2025-2026 Alex Ruban <alex@maximum.guru>
 * SPDX-FileCopyrightText: 2025-2026 Maximum Software Inc <contact@maximum.software>
 * SPDX-License-Identifier: GPL-3.0-only
 */

namespace Agenistrator\Events;

use Agenistrator\Event;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Progress_Event class.
 */
class Progress_Event extends Event {

	public const STATUS_RUNNING   = 'running';
	public const STATUS_COMPLETED = 'completed';
	public const STATUS_CANCELLED = 'cancelled';
	public const STATUS_FAILED    = 'failed';

	/**
	 * Operation identifier (e.g., 'embeddings')
	 *
	 * @var string
	 */
	private $operation;

	/**
	 * Instance identifier for this specific operation run
	 *
	 * @var string
	 */
	private $instance_id;

	/**
	 * Current progress value
	 *
	 * @var int
	 */
	private $current;

	/**
	 * Total items to process
	 *
	 * @var int
	 */
	private $total;

	/**
	 * Operation status: running, completed, cancelled, failed
	 *
	 * @var string
	 */
	private $status;

	/**
	 * Constructor.
	 *
	 * @param string $operation   The operation identifier (e.g., 'embeddings').
	 * @param int    $current     Current progress value.
	 * @param int    $total       Total items to process.
	 * @param string $status      Operation status (default: 'running').
	 * @param string $instance_id Unique instance ID for this operation run (optional).
	 * @since     1.0.0
	 */
	public function __construct( $operation, $current, $total, $status = self::STATUS_RUNNING, $instance_id = null ) {
		parent::__construct();
		$this->operation   = $operation;
		$this->instance_id = $instance_id;
		$this->current     = $current;
		$this->total       = $total;
		$this->status      = $status;
	}

	/**
	 * Get the event type.
	 *
	 * @return string
	 * @since     1.0.0
	 */
	public function get_type() {
		return 'progress';
	}

	/**
	 * Get the event data.
	 *
	 * @return array
	 * @since     1.0.0
	 */
	public function get_data() {
		return array(
			'operation'   => $this->operation,
			'instance_id' => $this->instance_id,
			'current'     => $this->current,
			'total'       => $this->total,
			'status'      => $this->status,
		);
	}

	/**
	 * Get the SSE payload for this event.
	 *
	 * @return array
	 * @since     1.0.0
	 */
	public function to_sse_payload() {
		return array_merge(
			parent::to_sse_payload(),
			array(
				'operation'   => $this->operation,
				'instance_id' => $this->instance_id,
				'current'     => $this->current,
				'total'       => $this->total,
				'status'      => $this->status,
			)
		);
	}

	/**
	 * Get the operation identifier.
	 *
	 * @return string
	 * @since     1.0.0
	 */
	public function get_operation() {
		return $this->operation;
	}

	/**
	 * Get the instance ID.
	 *
	 * @return string|null
	 * @since     1.0.0
	 */
	public function get_instance_id() {
		return $this->instance_id;
	}

	/**
	 * Get current progress value.
	 *
	 * @return int
	 * @since     1.0.0
	 */
	public function get_current() {
		return $this->current;
	}

	/**
	 * Get total items to process.
	 *
	 * @return int
	 * @since     1.0.0
	 */
	public function get_total() {
		return $this->total;
	}

	/**
	 * Get operation status.
	 *
	 * @return string
	 * @since     1.0.0
	 */
	public function get_status() {
		return $this->status;
	}

	/**
	 * Create an event from array data.
	 *
	 * @param array $data The event data.
	 * @return static
	 * @since     1.0.0
	 */
	public static function from_array( $data ) {
		$event_data = $data['data'] ?? $data;

		$event = new static(
			$event_data['operation'],
			$event_data['current'],
			$event_data['total'],
			$event_data['status'] ?? self::STATUS_RUNNING,
			$event_data['instance_id'] ?? null
		);

		if ( isset( $data['id'] ) ) {
			$event->set_id( $data['id'] );
		}

		return $event;
	}
}
