#[cfg(target_os = "linux")]
pub mod pyro {

    use pyroscope::backend::{BackendConfig, PprofConfig, pprof_backend};
    use pyroscope::pyroscope::{PyroscopeAgentBuilder, PyroscopeAgentRunning};
    use pyroscope::{PyroscopeAgent, PyroscopeError};

    use crate::common::debugger::PyroscopeConfig;

    pub struct PyroscopeState {
        pub config: PyroscopeConfig,
        pub agent: Option<PyroscopeAgent<PyroscopeAgentRunning>>,
    }

    impl PyroscopeState {
        fn build_agent(
            config: &PyroscopeConfig,
        ) -> Result<PyroscopeAgent<PyroscopeAgentRunning>, PyroscopeError> {
            // pprof uses tempfile::NamedTempFile which respects TMPDIR.
            // Qdrant's clear_all_tmp_directories() deletes TMPDIR on startup,
            // so we must ensure it exists before the profiler tries to create temp files.
            if let Ok(tmpdir) = std::env::var("TMPDIR") {
                let path = std::path::Path::new(&tmpdir);
                if !path.exists()
                    && let Err(err) = fs_err::create_dir_all(path)
                {
                    log::warn!("Failed to create TMPDIR {tmpdir}: {err}");
                }
            }

            let sample_rate = config.sampling_rate.unwrap_or(100);
            let pprof_config = PprofConfig { sample_rate };
            let backend_impl = pprof_backend(pprof_config, BackendConfig::default());

            log::info!(
                "Starting pyroscope agent with identifier {}",
                &config.identifier
            );
            // TODO: Add more tags like peerId and peerUrl
            let agent = PyroscopeAgentBuilder::new(
                config.url.clone(),
                "qdrant",
                sample_rate,
                "pyroscope-rs",
                env!("CARGO_PKG_VERSION"),
                backend_impl,
            )
            .tags(vec![("app", "Qdrant"), ("identifier", &config.identifier)])
            .build()?;
            let running_agent = agent.start()?;

            Ok(running_agent)
        }

        pub fn from_config(config: Option<PyroscopeConfig>) -> Option<Self> {
            match config {
                Some(pyro_config) => {
                    let agent = PyroscopeState::build_agent(&pyro_config);
                    match agent {
                        Ok(agent) => Some(PyroscopeState {
                            config: pyro_config,
                            agent: Some(agent),
                        }),
                        Err(err) => {
                            log::warn!("Pyroscope agent failed to start {err}");
                            None
                        }
                    }
                }
                None => None,
            }
        }

        pub fn stop_agent(&mut self) -> bool {
            log::info!("Stopping pyroscope agent");
            if let Some(agent) = self.agent.take() {
                return match agent.stop() {
                    Ok(stopped_agent) => {
                        log::info!("Stopped pyroscope agent. Shutting it down");
                        stopped_agent.shutdown();
                        log::info!("Pyroscope agent shut down completed.");
                        true
                    }
                    Err(err) => {
                        log::warn!("Pyroscope agent failed to stop {err}");
                        false
                    }
                };
            }
            true
        }
    }

    impl Drop for PyroscopeState {
        fn drop(&mut self) {
            self.stop_agent();
        }
    }
}

#[cfg(not(target_os = "linux"))]
pub mod pyro {
    use crate::common::debugger::PyroscopeConfig;

    pub struct PyroscopeState {}

    impl PyroscopeState {
        pub fn from_config(_config: Option<PyroscopeConfig>) -> Option<Self> {
            None
        }
    }
}
