//! Route matching result

use crate::core::BoxedHandler;
use crate::routing::Params;

/// Result of successful route matching.
///
/// The only production use is `into_parts()`, which the dispatcher calls to
/// extract the handler and params after a successful lookup.
pub struct Match<E = ()> {
    handler: BoxedHandler<E>,
    params: Params,
}

impl<E> Match<E> {
    pub fn new(handler: BoxedHandler<E>, params: Params) -> Self {
        Self { handler, params }
    }

    /// Consume the match and return handler and params.
    pub fn into_parts(self) -> (BoxedHandler<E>, Params) {
        (self.handler, self.params)
    }
}

#[cfg(test)]
impl<E> Match<E> {
    /// Test helper: borrow the params without consuming the match.
    pub fn params(&self) -> &Params {
        &self.params
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::domain::{Context, Response};

    fn make_handler<E: Send + Sync + 'static>() -> BoxedHandler<E> {
        BoxedHandler::new(|_ctx: Context<E>| async move { Ok(Response::text("test")) })
    }

    #[test]
    fn test_match_new_and_into_parts() {
        let params = Params::from(vec![("id".to_string(), "123".to_string())]);
        let (_, params) = Match::new(make_handler::<()>(), params).into_parts();
        assert_eq!(params.get("id"), Some("123"));
    }

    #[test]
    fn test_match_params_accessor() {
        let params = Params::from(vec![
            ("id".to_string(), "42".to_string()),
            ("name".to_string(), "alice".to_string()),
        ]);
        let m = Match::new(make_handler::<()>(), params);
        assert_eq!(m.params().get("id"), Some("42"));
        assert_eq!(m.params().get("name"), Some("alice"));
        assert_eq!(m.params().len(), 2);
    }

    #[test]
    fn test_match_empty_params() {
        let m = Match::new(make_handler::<()>(), Params::new());
        assert!(m.params().is_empty());
    }

    #[test]
    fn test_match_multiple_params() {
        let params = Params::from(vec![
            ("user_id".to_string(), "42".to_string()),
            ("post_id".to_string(), "99".to_string()),
        ]);
        let m = Match::new(make_handler::<()>(), params);
        assert_eq!(m.params().get("user_id"), Some("42"));
        assert_eq!(m.params().get("post_id"), Some("99"));
    }
}
