use crate::cmd::config::{populate_system, resolve_config, ConfigArgsRef};
use crate::cmd::CliContext;
use clap::Parser;
use eternaltwin_core::types::{DisplayErrorChainExt, WeakError};
use eternaltwin_services::job::archive_twinoid_users_single_token::{
  ArchiveTwinoidUsersSingleToken, ArchiveTwinoidUsersWorker,
};
use eternaltwin_system::EternaltwinSystem;
use std::sync::Arc;
use std::time::Duration;

/// Arguments to the `backend` task.
#[derive(Debug, Parser)]
pub struct Args {
  #[clap(flatten)]
  config: crate::cmd::config::Args,
  token: String,
  start: u32,
  end: u32,
}

impl ConfigArgsRef for Args {
  fn config_args(&self) -> &crate::cmd::config::Args {
    &self.config
  }
}

pub async fn run(cx: CliContext<'_, Args>) -> Result<(), WeakError> {
  let config = resolve_config(&cx, false).await?;
  let system = EternaltwinSystem::create_dyn(&config, cx.out)
    .await
    .map_err(WeakError::wrap)?;
  // job_runtime.register::<ArchiveTwinoidUsersSingleToken>();

  eprintln!("loaded internal Eternaltwin system");

  populate_system(&system, &config, false).await?;

  eprintln!("initialization complete");

  let job_rt = {
    let job_rt = Arc::clone(&system.job_runtime);

    job_rt
      .spawn(
        ArchiveTwinoidUsersSingleToken(ArchiveTwinoidUsersWorker::Start {
          token: cx.args.token.parse().unwrap(),
          range: cx.args.start..cx.args.end,
        }),
        None,
      )
      .await
      .unwrap();

    async move {
      if let Err(e) = job_rt.tick().await {
        eprintln!("job_rt.tick error: {}", e.display_chain());
        eprintln!("job_runtime tick error, sleep for 10min");
        tokio::time::sleep(Duration::from_secs(600)).await;
      }
      if let Err(e) = job_rt.wait_for_available().await {
        eprintln!("job_rt.tick error {}", e.display_chain());
        eprintln!("job_runtime tick error, sleep for 10min");
        tokio::time::sleep(Duration::from_secs(600)).await;
      };
    }
  };

  job_rt.await;

  Ok(())
}
