use crate::component::XjBridgeRuntime;
use crate::config::Direction;
use crate::producer::XjProducer;
use camel_component_api::{
    BoxProcessor, CamelError, Consumer, Endpoint, ProducerContext, RuntimeObservability,
};
use camel_xslt::StylesheetId;
use std::sync::Arc;

/// XML↔JSON transformation endpoint.
///
/// # Body Contract
///
/// Input: XML or JSON string/bytes depending on `transform_direction`
/// Output: transformed JSON or XML string
pub struct XjEndpoint {
    uri: String,
    stylesheet_id: StylesheetId,
    params: Vec<(String, String)>,
    client: Arc<camel_xslt::XsltBridgeClient>,
    runtime: Arc<XjBridgeRuntime>,
    direction: Direction,
    max_payload_bytes: Option<usize>,
    retry_count: u32,
    retry_delay_ms: u64,
}

impl XjEndpoint {
    #[allow(clippy::too_many_arguments)]
    pub fn new(
        uri: String,
        stylesheet_id: StylesheetId,
        params: Vec<(String, String)>,
        client: Arc<camel_xslt::XsltBridgeClient>,
        runtime: Arc<XjBridgeRuntime>,
        direction: Direction,
        max_payload_bytes: Option<usize>,
        retry_count: u32,
        retry_delay_ms: u64,
    ) -> Self {
        Self {
            uri,
            stylesheet_id,
            params,
            client,
            runtime,
            direction,
            max_payload_bytes,
            retry_count,
            retry_delay_ms,
        }
    }
}

impl Endpoint for XjEndpoint {
    fn uri(&self) -> &str {
        &self.uri
    }

    fn create_consumer(
        &self,
        _rt: Arc<dyn RuntimeObservability>,
    ) -> Result<Box<dyn Consumer>, CamelError> {
        Err(CamelError::EndpointCreationFailed(
            "xj endpoint does not support consumers".to_string(),
        ))
    }

    fn create_producer(
        &self,
        _rt: Arc<dyn RuntimeObservability>,
        _ctx: &ProducerContext,
    ) -> Result<BoxProcessor, CamelError> {
        Ok(BoxProcessor::new(XjProducer::new(
            self.stylesheet_id.clone(),
            self.params.clone(),
            Arc::clone(&self.client),
            Arc::clone(&self.runtime),
            self.direction,
            self.max_payload_bytes,
            self.retry_count,
            self.retry_delay_ms,
        )))
    }
}
