//! [`ApidocHandlerOps`] — per-handler hook for mutating the
//! [`utoipa::openapi::path::Operation`] generated by `#[utoipa::path]`
//! after it lands in a [`utoipa::openapi::path::Paths`] map.
//!
//! Sister trait to [`crate::ApidocHandlerSchemas`]: the method macro
//! emits an impl on the per-handler `__path_<fn>` struct that walks
//! every argument type through autoref-specialized
//! [`crate::__private::OpSecurityContribution`] probes. Argument
//! types that implement [`crate::DocOperationSecurity`] mutate the
//! operation in place; types that don't silently no-op.
//!
//! The extended [`crate::routes!`] macro calls
//! [`ApidocHandlerOps::augment`] for every handler so the
//! contributions land before the [`utoipa_axum::router::OpenApiRouter`]
//! merges the handler's [`utoipa::openapi::path::Paths`] into the
//! global document.

use utoipa::openapi::path::{HttpMethod, Operation, PathItem, Paths};

/// Per-handler hook that mutates the [`Operation`] generated by
/// `#[utoipa::path]` for this handler. Implemented by the method
/// macro on the same `__path_<fn>` struct that carries the `utoipa`
/// path metadata; the impl iterates every handler argument through
/// the [`crate::DocOperationSecurity`] probe.
///
/// Called by the extended [`crate::routes!`] macro on the
/// [`Paths`] returned from `utoipa_axum::routes!()` before merging
/// into the router. Idempotent — calling [`Self::augment`] twice on
/// the same paths leaves the operation unchanged.
pub trait ApidocHandlerOps {
    /// Apply per-operation augmentations to the operation(s) this
    /// handler owns inside `paths`. Implementations match on
    /// `<Self as utoipa::Path>::path()` and
    /// `<Self as utoipa::Path>::methods()` to pick out the relevant
    /// operation(s); no-op when no matching operation is present.
    fn augment(paths: &mut Paths);
}

/// Find the operation slot on a [`PathItem`] for a given
/// [`HttpMethod`]. Used by the method-macro-generated
/// [`ApidocHandlerOps`] impl to pick out the operation matching the
/// handler's declared methods.
pub fn operation_for_method_mut(item: &mut PathItem, method: HttpMethod) -> Option<&mut Operation> {
    match method {
        HttpMethod::Get => item.get.as_mut(),
        HttpMethod::Put => item.put.as_mut(),
        HttpMethod::Post => item.post.as_mut(),
        HttpMethod::Delete => item.delete.as_mut(),
        HttpMethod::Options => item.options.as_mut(),
        HttpMethod::Head => item.head.as_mut(),
        HttpMethod::Patch => item.patch.as_mut(),
        HttpMethod::Trace => item.trace.as_mut(),
    }
}
