use crate::prelude::*;
use humantime::parse_duration;

/// Options for batch processing
#[derive(Options, Clone, Debug, Deserialize, Serialize)]
#[allow(clippy::struct_excessive_bools)]
pub struct BatchOptions {
    /// Should the spectrogram command be executed?
    #[arg(long)]
    pub spectrogram: bool,

    /// Should the transcode command be executed?
    #[arg(long)]
    pub transcode: bool,

    /// Should failed transcodes be retried?
    #[arg(long)]
    pub retry_transcode: bool,

    /// Should the upload command be executed?
    #[arg(long)]
    pub upload: bool,

    /// Limit the number of torrents to batch process.
    ///
    /// If `no_limit` is set, this option is ignored.
    #[arg(long)]
    #[options(default = 3)]
    pub limit: usize,

    /// Should the `limit` option be ignored?
    #[arg(long)]
    pub no_limit: bool,

    /// Wait for a duration before uploading the torrent.
    ///
    /// The duration is a string that can be parsed such as `500ms`, `5m`, `1h30m15s`.
    #[arg(long)]
    pub wait_before_upload: Option<String>,
}

impl BatchOptions {
    /// Parsed `wait_before_upload` duration, or `None` if unset or unparseable.
    #[must_use]
    pub fn get_wait_before_upload(&self) -> Option<Duration> {
        let wait_before_upload = self.wait_before_upload.clone()?;
        parse_duration(wait_before_upload.as_str()).ok()
    }

    /// Effective batch limit, or `None` if `no_limit` is set.
    #[must_use]
    pub fn get_limit(&self) -> Option<usize> {
        if self.no_limit {
            None
        } else {
            Some(self.limit)
        }
    }
}

impl OptionsContract for BatchOptions {
    type Partial = BatchOptionsPartial;

    fn validate(&self, validator: &mut OptionsValidator) {
        if let Some(wait_before_upload) = &self.wait_before_upload
            && let Err(error) = parse_duration(wait_before_upload.as_str())
        {
            validator.push(OptionIssue::duration_invalid(
                "wait_before_upload",
                wait_before_upload,
                &error.to_string(),
            ));
        }
        validator.check_dependent("upload", self.upload, "transcode", self.transcode);
    }
}
