use std::env;
use std::path::{Path, PathBuf};
use std::sync::Mutex;

use globset::{GlobBuilder, GlobMatcher};
use walkdir::WalkDir;

use crate::env::get_tool_config;
use crate::settings::Settings;
use crate::utils::style;

pub(crate) struct GlobCollector {
    pub(crate) fail_fast: bool,
    pub(crate) failed: usize,
    pub(crate) show_insta_hint: bool,
}

// the glob stack holds failure count + an indication if cargo insta review
// should be run.
lazy_static::lazy_static! {
    pub(crate) static ref GLOB_STACK: Mutex<Vec<GlobCollector>> = Mutex::default();
}

lazy_static::lazy_static! {
    static ref GLOB_FILTER: Vec<GlobMatcher> = {
        env::var("INSTA_GLOB_FILTER")
            .unwrap_or_default()
            .split(';')
            .filter(|x| !x.is_empty())
            .filter_map(|filter| {
                GlobBuilder::new(filter)
                    .case_insensitive(true)
                    .build()
                    .ok()
                    .map(|x| x.compile_matcher())
            })
            .collect()
    };
}

pub fn glob_exec<F: FnMut(&Path)>(manifest_dir: &str, base: &Path, pattern: &str, mut f: F) {
    // If settings.allow_empty_glob() == true and `base` doesn't exist, skip
    // everything. This is necessary as `base` is user-controlled via `glob!/3`
    // and may not exist.
    let mut settings = Settings::clone_current();

    if settings.allow_empty_glob() && !base.exists() {
        return;
    }

    let glob = GlobBuilder::new(pattern)
        .case_insensitive(true)
        .literal_separator(true)
        .build()
        .unwrap()
        .compile_matcher();

    let walker = WalkDir::new(base).follow_links(true);
    let mut glob_found_matches = false;

    GLOB_STACK.lock().unwrap().push(GlobCollector {
        failed: 0,
        show_insta_hint: false,
        fail_fast: get_tool_config(manifest_dir).glob_fail_fast(),
    });

    // step 1: collect all matching files
    let mut matching_files = vec![];
    for file in walker {
        let file = file.unwrap();
        let path = file.path();
        let stripped_path = path.strip_prefix(base).unwrap_or(path);
        if !glob.is_match(stripped_path) {
            continue;
        }

        glob_found_matches = true;

        // if there is a glob filter, skip if it does not match this path
        if !GLOB_FILTER.is_empty() && !GLOB_FILTER.iter().any(|x| x.is_match(stripped_path)) {
            eprintln!("Skipping {} due to glob filter", stripped_path.display());
            continue;
        }

        matching_files.push(path.to_path_buf());
    }

    // step 2: sort, determine common prefix and run assertions
    matching_files.sort();
    let common_prefix = find_common_prefix(&matching_files);
    for path in &matching_files {
        settings.set_input_file(path);

        // if there is a common prefix, use that stirp down the input file.  That way we
        // can ensure that a glob like inputs/*/*.txt with a/file.txt and b/file.txt
        // does not create two identical snapshot suffixes.  Instead of file.txt for both
        // it would end up as a/file.txt and b/file.txt.
        let snapshot_suffix = if let Some(prefix) = common_prefix {
            path.strip_prefix(prefix).unwrap().as_os_str()
        } else {
            path.file_name().unwrap()
        };

        settings.set_snapshot_suffix(snapshot_suffix.to_str().unwrap());
        settings.bind(|| {
            f(path);
        });
    }

    let top = GLOB_STACK.lock().unwrap().pop().unwrap();
    if !glob_found_matches && !settings.allow_empty_glob() {
        panic!("the glob! macro did not match any files.");
    }

    if top.failed > 0 {
        if top.show_insta_hint {
            println!(
                "{hint}",
                hint = style("To update snapshots run `cargo insta review`").dim(),
            );
        }
        if top.failed > 1 {
            println!(
                "{hint}",
                hint = style("To enable fast failing for glob! export INSTA_GLOB_FAIL_FAST=1 as environment variable.").dim()
            );
        }
        panic!(
            "glob! resulted in {} snapshot assertion failure{}",
            top.failed,
            if top.failed == 1 { "" } else { "s" },
        );
    }
}

fn find_common_prefix(sorted_paths: &[PathBuf]) -> Option<&Path> {
    let first = sorted_paths.first()?;
    let last = sorted_paths.last()?;
    let prefix_len = first
        .components()
        .zip(last.components())
        .take_while(|(a, b)| a == b)
        .count();

    if prefix_len == 0 {
        None
    } else {
        let mut prefix = first.components();
        for _ in 0..first.components().count() - prefix_len {
            prefix.next_back();
        }
        Some(prefix.as_path())
    }
}
