//! Dependencies handed to a plugin at boot.

use std::sync::Arc;

use tokio::sync::watch;

use crate::executor::Executor;
use crate::health::HealthRegistry;
use crate::metrics::MetricsRegistry;
use crate::role::PluginRole;
use crate::rpc::RpcRegistrar;

/// The worker pool a plugin instance is running in (phase 85).
///
/// In the fork-after-warm model an operator can scale subsystems independently
/// by giving a plugin its own worker pool (`[http].workers`, `[jobs].workers`).
/// A plugin that must be reachable from *every* pool — because other pools call
/// into it (e.g. `jobs.push`, invoked from HTTP handlers) — declares
/// [`Plugin::runs_in_every_pool`](crate::Plugin::runs_in_every_pool) and is
/// booted in each one. Such a plugin uses [`primary`](Self::primary) to tell its
/// **owning** pool (do the full work: run consumers) from pools where it exists
/// only to expose a cross-cutting capability (push-only, no consumers).
#[derive(Debug, Clone)]
pub struct PoolContext {
    /// Pool label: the plugin name for a dedicated pool, `"shared"` otherwise.
    pub label: String,
    /// `true` in the plugin's owning pool (its dedicated pool, or the shared
    /// pool when it has no dedicated one); `false` where the plugin is present
    /// only as a cross-cutting producer. Single-pool plugins (http/grpc) are
    /// always `true` in the one pool they run in.
    pub primary: bool,
}

/// What every plugin receives in [`Plugin::boot`](crate::Plugin::boot).
///
/// All fields are cheaply cloneable (`Arc` or `Receiver`).
#[derive(Clone)]
pub struct PluginContext {
    /// Which process this plugin instance is booting in (phase 79).
    ///
    /// In the **master** the `executor` is a
    /// [`NoopExecutor`](crate::NoopExecutor) (no PHP); in a **worker** it
    /// dispatches into that worker's PHP runtime. A [`Placement::Both`] plugin
    /// branches on this; single-placement plugins can ignore it.
    ///
    /// [`Placement::Both`]: crate::Placement::Both
    pub role: PluginRole,

    /// Send work to a PHP worker.
    ///
    /// Valid only when [`role`](Self::role) is [`PluginRole::Worker`]; in the
    /// master it is a [`NoopExecutor`](crate::NoopExecutor) whose methods return
    /// `Err`.
    pub executor: Arc<dyn Executor>,

    /// Fires `true` when the server is shutting down.
    pub shutdown: watch::Receiver<bool>,

    /// Register RPC method handlers. `None` if not available.
    pub rpc_registrar: Option<Arc<dyn RpcRegistrar>>,

    /// Register health checks. `None` if not available.
    pub health_registry: Option<Arc<dyn HealthRegistry>>,

    /// Register metrics. `None` if not available.
    pub metrics_registry: Option<Arc<dyn MetricsRegistry>>,

    /// The worker pool this instance runs in (phase 85). `None` in the master
    /// and on the legacy single-process path (treat as "owning pool"). A plugin
    /// that [`runs_in_every_pool`](crate::Plugin::runs_in_every_pool) reads
    /// [`primary`](PoolContext::primary) to decide full-work vs push-only.
    pub pool: Option<PoolContext>,
}
