use fts_index::storage::meta::StorageMeta;
use log::*;
use tokio::spawn;

use crate::searcher::Searcher;
use crate::Args;
use std::sync::Arc;

pub(crate) struct State {
    pub(crate) searcher: Arc<Searcher>,
    pub(crate) storage: Option<Arc<dyn cloud::Storage>>,
}

pub type ApiState = Arc<State>;

impl State {}

pub(crate) async fn new(args: Args) -> anyhow::Result<ApiState> {
    let storage = if args.locally {
        info!("Loadding local");
        None
    } else {
        info!("Loadding cloud storage");
        Some(Arc::new(cloud::s3::S3Service::default()) as Arc<dyn cloud::Storage>)
    };

    let searcher = Arc::new(Searcher::new(&args.path, storage.clone()).await?);

    spawn(auto_reload_version(storage.clone(), searcher.clone()));

    Ok(Arc::new(State { searcher, storage }))
}

async fn auto_reload_version(storage: Option<Arc<dyn cloud::Storage>>, searcher: Arc<Searcher>) {
    let storage = match storage {
        Some(storage) => storage,
        None => return,
    };
    let reload_interval: u64 = std::env::var("AUTO_RELOAD_INDEX_INTERVAL")
        .unwrap_or_else(|_| "60".to_string())
        .parse()
        .unwrap_or(60);
    loop {
        let version = match StorageMeta::get_cloud_version(storage.clone()).await {
            Ok(v) => v,
            Err(e) => {
                let msg = format!("Failed to get cloud version: {:?}", e);
                warn!("{}", msg);
                notice::feishu::warn(&msg, Some("serving-service:AutoReloadVersion")).await;
                tokio::time::sleep(std::time::Duration::from_secs(reload_interval)).await;
                continue;
            }
        };

        debug!("Try to auto_reload_version with version: {}", version);

        if let Err(e) = searcher.shift_index_version(storage.clone(), version).await {
            warn!("Failed to auto_reload_version: {:?}", e);
            notice::feishu::warn(
                &format!("Failed to auto_reload_version: {:?}", e),
                Some("serving-service:AutoReloadVersion"),
            )
            .await;
        }

        tokio::time::sleep(std::time::Duration::from_secs(reload_interval)).await;
    }
}
