use std::path::PathBuf;

use crate::{
    common::{
        list_of_regions::{CliRegionsArgs, CliTargetsArgs},
        reference::CliReferenceArg,
    },
    vcf::pipeline::{self, PipelineSettings, clusterizer::local_phasing::PhasingSettings},
};

#[derive(clap::Args, Debug, Default)]
#[group(multiple = false)]
pub struct OutputFilter {
    /// When enabled, only records that result in a successful realignment are written to the output.
    #[arg(long)]
    pub only_realigned: bool,

    /// When enabled, records that result in a successful realignment are written to the output, as well as any records that are within the given number of bases of such records.
    #[arg(long, value_name = "BASES")]
    pub realigned_and_context: Option<u64>,
}

#[derive(clap::Args, Debug, Default)]
pub struct OutputOptions {
    /// The output VCF file. If none is given, or it is `-`, stdout is used.
    #[arg(short = 'o', long = "output", value_name = "FILE")]
    pub output_file: Option<String>,

    #[command(flatten)]
    pub output_filter: OutputFilter,
}

impl<T: ToString> From<Option<T>> for OutputOptions {
    fn from(value: std::option::Option<T>) -> Self {
        Self {
            output_file: value.map(|v| v.to_string()),
            output_filter: OutputFilter::default(),
        }
    }
}

/// Re-annotate VCF files
#[derive(clap::Args, Debug)]
pub struct Command {
    /// The input vcf file, or `-` to read from stdin.
    pub input: String,

    #[command(flatten)]
    pub reference: CliReferenceArg,

    #[command(flatten)]
    pub regions: CliRegionsArgs,

    #[command(flatten)]
    pub targets: CliTargetsArgs,

    #[command(flatten)]
    pub output: OutputOptions,

    /// Do not append version and command line to the header
    #[arg(long = "no-version")]
    pub no_version: bool,

    /// Optionally, a file where to write the regions where there was a template switch. Can be `-` to output on stdout, but then the output file (-o/--output) must be specified as a file.
    /// By default, the regions will be output as a tab-delimited three-column file: (CHROM, POS, END), 1-based and closed. If the specified filename ends with ".bed", the output will be
    /// 0-based and half-open, like usual with the BED file standard.
    #[arg(long = "output-regions", value_name = "FILE")]
    pub ts_regions: Option<String>,

    #[arg(long = "csv", value_name = "FILE")]
    pub csv_output: Option<PathBuf>,

    /// Optional BAM file (with index) used for local read-based phasing of unphased heterozygous records.
    #[arg(long = "phasing-bam", value_name = "FILE")]
    pub phasing_bam: Option<String>,

    #[command(flatten)]
    pub phasing: PhasingSettings,

    #[command(flatten)]
    pub pipeline_settings: pipeline::PipelineSettings,
}

impl Default for Command {
    fn default() -> Self {
        Self {
            input: "-".into(),
            reference: CliReferenceArg::default(),
            regions: CliRegionsArgs::default(),
            targets: CliTargetsArgs::default(),
            output: OutputOptions::default(),
            no_version: false,
            ts_regions: None,
            pipeline_settings: PipelineSettings::default(),
            csv_output: None,
            phasing_bam: None,
            phasing: PhasingSettings::default(),
        }
    }
}
