use crate::{
    commands::bcftools::{bcftools_keep_pass, BcftoolsConfig},
    runners::{run_wait, CommandRun},
};
use anyhow::Context;
use std::{fs, path::Path};
use tracing::info;

#[derive(Debug, Clone)]
pub struct WakhanConfig {
    pub bin: String,
    pub result_dir: String,
    pub threads: u8,
    pub vntr_bed: String,
    pub pon: String,
    pub conda_sh: String,
    pub force: bool,
}
// savana --tumour /data/longreads_basic_pipe/CUNY/diag/CUNY_diag_hs1_hp.bam --normal /data/longreads_basic_pipe/CUNY/mrd/CUNY_mrd_hs1_hp.bam --outdir /data/longreads_basic_pipe/CUNY/diag/savana --ref /data/ref/hs1/chm13v2.0.fa --phased_vcf /data/longreads_basic_pipe/CUNY/diag/ClairS/clair3_normal_germline_output_PS.vcf --no_blacklist

// python /data/tools/Wakhan/src/main.py --threads 150 --reference /data/ref/hs1/chm13v2.0.fa --target-bam /data/longreads_basic_pipe/CUNY/diag/CUNY_diag_hs1_hp.bam --normal-phased-vcf /data/longreads_basic_pipe/CUNY/diag/ClairS/clair3_normal_tumoral_germline_output.vcf.gz --genome-name hs1 --out-dir-plots /data/longreads_basic_pipe/CUNY/diag/wakhan/ --breakpoints /data/longreads_basic_pipe/CUNY/diag/severus/somatic_SVs/severus_somatic.vcf --loh-enable --pdf-enable --centromere /data/tools/Wakhan/src/annotations/chm13v2_cen_coord.bed

impl Default for WakhanConfig {
    fn default() -> Self {
        Self {
            bin: "/data/tools/Wakhan/src/main.py".to_string(),
            result_dir: "/data/longreads_basic_pipe".to_string(),
            threads: 155,
            vntr_bed: "/data/ref/hs1/vntrs_chm13.bed".to_string(),
            pon: "/data/ref/hs1/PoN_1000G_chm13.tsv.gz".to_string(),
            conda_sh: "/data/miniconda3/etc/profile.d/conda.sh".to_string(),
            force: true,
        }
    }
}

#[derive(Debug)]
pub struct Wakhan {
    pub id: String,
    pub output_dir: String,
    pub diag_bam: String,
    pub mrd_bam: String,
    pub phased_vcf: String,
    pub output_vcf: String,
    pub vcf_passed: String,
    pub config: WakhanConfig,
    pub log_dir: String,
}

impl Wakhan {
    pub fn new(
        id: &str,
        diag_bam: &str,
        mrd_bam: &str,
        phased_vcf: &str,
        config: WakhanConfig,
    ) -> Self {
        let output_dir = format!("{}/{}/diag/severus", config.result_dir, id);
        let output_vcf = format!("{output_dir}/somatic_SVs/severus_somatic.vcf");
        let vcf_passed = format!("{output_dir}/{id}_diag_severus_PASSED.vcf.gz",);

        let log_dir = format!("{}/{}/log/severus", config.result_dir, id);
        Self {
            id: id.to_string(),
            output_dir,
            diag_bam: diag_bam.to_string(),
            mrd_bam: mrd_bam.to_string(),
            config,
            phased_vcf: phased_vcf.to_string(),
            log_dir,
            output_vcf,
            vcf_passed,
        }
    }

    pub fn run(&mut self) -> anyhow::Result<()> {
        if self.config.force && Path::new(&self.output_vcf).exists() {
            fs::remove_dir_all(&self.output_dir)?;
        }

        if !Path::new(&self.log_dir).exists() {
            fs::create_dir_all(&self.log_dir).expect("Failed to create output directory");
        }

        // Run command if output VCF doesn't exist
        if !Path::new(&self.output_vcf).exists() {
            let severus_args = [
                "--target-bam",
                &self.diag_bam,
                "--control-bam",
                &self.mrd_bam,
                "--phasing-vcf",
                &self.phased_vcf,
                "--out-dir",
                &self.output_dir,
                "-t",
                &self.config.threads.to_string(),
                "--write-alignments",
                "--use-supplementary-tag",
                "--resolve-overlaps",
                "--between-junction-ins",
                "--vntr-bed",
                &self.config.vntr_bed,
            ];
            let args = [
                "-c",
                &format!("source {} && conda activate severus_env && {} {}", self.config.conda_sh, self.config.bin, severus_args.join(" ")),
            ];
            let mut cmd_run = CommandRun::new("bash", &args);
            let report = run_wait(&mut cmd_run).context(format!(
                "Error while running `severus.py {}`",
                args.join(" ")
            ))?;

            let log_file = format!("{}/severus_", self.log_dir);
            report
                .save_to_file(&log_file)
                .context(format!("Error while writing logs into {log_file}"))?;
        } else {
            info!("Wakhan output vcf already exists");
        }

        // Keep PASS
        if !Path::new(&self.vcf_passed).exists() {
            let report = bcftools_keep_pass(
                &self.output_vcf,
                &self.vcf_passed,
                BcftoolsConfig::default(),
            )
            .context(format!(
                "Error while running bcftools keep PASS for {}",
                &self.output_vcf
            ))?;
            let log_file = format!("{}/bcftools_pass", self.log_dir);
            report
                .save_to_file(&log_file)
                .context(format!("Error while writing logs into {log_file}"))?;
        }
        Ok(())
    }
}
