// Copyright 2024 RustFS Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Shared backpressure policy type.
//!
//! This module only carries the watermark policy; the admission primitive it
//! projects into lives in `rustfs-io-core`.

use rustfs_io_core::BackpressureConfig as CoreBackpressureConfig;

/// Watermark policy for duplex-pipe backpressure.
#[derive(Debug, Clone, Copy)]
pub struct PipeBackpressurePolicy {
    /// Buffer size in bytes
    pub buffer_size: usize,
    /// High watermark percentage
    pub high_watermark: u32,
    /// Low watermark percentage
    pub low_watermark: u32,
}

impl Default for PipeBackpressurePolicy {
    fn default() -> Self {
        Self {
            buffer_size: 4 * 1024 * 1024, // 4MB
            high_watermark: 80,
            low_watermark: 50,
        }
    }
}

impl PipeBackpressurePolicy {
    /// Calculate high watermark threshold in bytes
    pub fn high_watermark_bytes(&self) -> usize {
        (self.buffer_size as u64 * self.high_watermark as u64 / 100) as usize
    }

    /// Calculate low watermark threshold in bytes
    pub fn low_watermark_bytes(&self) -> usize {
        (self.buffer_size as u64 * self.low_watermark as u64 / 100) as usize
    }

    /// Convert the policy into the reusable io-core admission-pressure config.
    ///
    /// The caller still owns duplex buffer sizing, but the shared
    /// overload/admission primitive lives in `io-core`.
    pub fn to_core_config(&self) -> CoreBackpressureConfig {
        CoreBackpressureConfig {
            max_concurrent: 32,
            high_water_mark: self.high_watermark as f64 / 100.0,
            low_water_mark: self.low_watermark as f64 / 100.0,
            cooldown: std::time::Duration::from_millis(100),
            enabled: true,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_backpressure_policy_defaults() {
        let config = PipeBackpressurePolicy::default();
        assert_eq!(config.buffer_size, 4 * 1024 * 1024);
        assert!(config.high_watermark > config.low_watermark);
    }

    #[test]
    fn test_backpressure_policy_watermark_bytes() {
        let config = PipeBackpressurePolicy {
            buffer_size: 1000,
            high_watermark: 80,
            low_watermark: 50,
        };
        assert_eq!(config.high_watermark_bytes(), 800);
        assert_eq!(config.low_watermark_bytes(), 500);
    }

    #[test]
    fn test_backpressure_policy_to_core_config() {
        let policy = PipeBackpressurePolicy::default();
        let core = policy.to_core_config();
        assert_eq!(core.high_water_mark, policy.high_watermark as f64 / 100.0);
        assert_eq!(core.low_water_mark, policy.low_watermark as f64 / 100.0);
        assert!(core.enabled);
    }
}
