// Copyright 2025 PingCAP, Inc.

use std::{path::PathBuf, sync::Arc};

use kvengine::ia::{
    gc::{IaFileGcState, IaGcConfig, IaGcRunner},
    manager::IaManager,
};
use tikv_util::{config::ReadableDuration, info};

use crate::common::Running;

#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[serde(default)]
#[serde(rename_all = "kebab-case")]
pub struct LocalGcConfig {
    pub interval: ReadableDuration,
    pub ia: IaGcConfig,
}

impl Default for LocalGcConfig {
    fn default() -> Self {
        Self {
            interval: ReadableDuration::hours(1),
            ia: IaGcConfig::default(),
        }
    }
}

pub struct LocalGcRunner {
    config: LocalGcConfig,
    ia_runner: IaGcRunner,
}

impl LocalGcRunner {
    pub fn new(config: LocalGcConfig, ia_mgr: IaManager, meta_paths: Arc<Vec<PathBuf>>) -> Self {
        let ia_runner = IaGcRunner::new(config.ia.clone(), ia_mgr.clone(), meta_paths);
        Self { config, ia_runner }
    }

    pub fn run(&mut self, running: Running) {
        info!("worker gc runner start"; "config" => ?self.config);

        while running.get() {
            self.ia_runner.run(|_| IaFileGcState::NotLive);

            std::thread::sleep(self.config.interval.0);
        }

        info!("worker gc runner stopped");
    }
}

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

    #[test]
    fn meta_lifetime_controls_worker_not_live_meta_lifetime() {
        let config: LocalGcConfig = toml::from_str(
            r#"
interval = "1h"

[ia]
meta-lifetime = "2h"
"#,
        )
        .unwrap();

        assert_eq!(config.ia.meta_lifetime, ReadableDuration::hours(2));
    }
}
