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

use crate::{Backend, UnitHttpRequest, UnitHttpResponse};
use std::cell::RefCell;
use std::collections::VecDeque;

/// A [Backend] that stores the incoming requests to be later retrieved by the test.
/// Delegates the response generation to the function provided in the constructor.
/// This classes uses the interior mutability pattern to allow the test to retrieve the requests.
///
/// # Example
///
/// ```ignore
///        let back = Rc::new(TraceBackend::new(echo_backend));
///
///         let mut tester = UnitTestBuilder::default()
///             .with_config(config)
///             .with_backend(Rc::clone(&back))
///             .with_entrypoint(crate::configure);
///
///         let response = tester.request(req.clone());
///         let request = back.next().unwrap();
/// ```
pub struct TraceBackend<B: Backend> {
    response: B,
    calls: RefCell<VecDeque<UnitHttpRequest>>,
}

impl<B: Backend> TraceBackend<B> {
    /// Creates a new instance with the provided backend for response generation.
    pub fn new(response: B) -> Self {
        Self {
            response,
            calls: Default::default(),
        }
    }

    /// Removes and returns the next request that reached the backend.
    pub fn next(&self) -> Option<UnitHttpRequest> {
        self.calls.borrow_mut().pop_front()
    }
}

impl<B: Backend> Backend for TraceBackend<B> {
    fn call(&self, req: UnitHttpRequest) -> UnitHttpResponse {
        self.calls.borrow_mut().push_back(req.clone());
        self.response.call(req)
    }
}
