// Copyright (c) 2026, Salesforce, Inc.,
// All rights reserved.
// For full license text, see the LICENSE.txt file

//! Readiness
//!
//! Contains the resource to indicate that a policies that require async initialization
//! have completed their initialization.
//!

use classy::extract::context::ConfigureContext;
use classy::extract::{Extract, FromContext};
use classy::{MetricType, MetricsHost};
use pdk_core::log::debug;
use pdk_core::policy_context::api::Metadata;
use std::convert::Infallible;
use std::rc::Rc;

/// Used to indicate that a policy which extends the `async-initialization-wasm` has
/// completed its initialization.
pub trait Readiness {
    fn ready(&self);
}

/// Implementation of the Readiness trait that can be injected into a policy.
pub struct ReadinessInstance {
    metrics: Rc<dyn MetricsHost>,
    name: String,
}

impl Readiness for ReadinessInstance {
    fn ready(&self) {
        debug!("creating metric {}", self.name);
        let id = self.metrics.define_metric(MetricType::Gauge, &self.name);
        self.metrics.record_metric(id, 1);
    }
}

/// It can injected by the framework during the configuration phase of the policy lifecycle:
///
/// ``` rust
/// #[entrypoint]
/// async fn configure(
///     launcher: Launcher,
///     Configuration(configuration): Configuration,
///     readiness: ReadinessInstance,
/// ) -> Result<()> {
///     // your code here.
/// }
impl FromContext<ConfigureContext> for ReadinessInstance {
    type Error = Infallible;

    fn from_context(context: &ConfigureContext) -> Result<Self, Self::Error> {
        let metadata: Metadata = context.extract()?;
        let metrics: Rc<dyn MetricsHost> = context.extract()?;

        let name = format!(
            "{}/{}/ready",
            metadata.policy_metadata.policy_namespace, metadata.policy_metadata.policy_name
        );

        Ok(ReadinessInstance { metrics, name })
    }
}
