use std::borrow::Cow;
use std::cell::RefCell;
use std::collections::{BTreeMap, BTreeSet};
use std::error::Error;
use std::fs;
use std::io::Write;
use std::path::{Path, PathBuf};
use std::str;
use std::sync::{Arc, Mutex};

use crate::env::{
    get_cargo_workspace, get_tool_config, memoize_snapshot_file, snapshot_update_behavior,
    OutputBehavior, SnapshotUpdateBehavior, ToolConfig,
};
use crate::output::SnapshotPrinter;
use crate::settings::Settings;
use crate::snapshot::{MetaData, PendingInlineSnapshot, Snapshot, SnapshotContents};
use crate::utils::{path_to_storage, style};

lazy_static::lazy_static! {
    static ref TEST_NAME_COUNTERS: Mutex<BTreeMap<String, usize>> =
        Mutex::new(BTreeMap::new());
    static ref TEST_NAME_CLASH_DETECTION: Mutex<BTreeMap<String, bool>> =
        Mutex::new(BTreeMap::new());
    static ref INLINE_DUPLICATES: Mutex<BTreeSet<String>> =
        Mutex::new(BTreeSet::new());
}

thread_local! {
    static RECORDED_DUPLICATES: RefCell<Vec<BTreeMap<String, Snapshot>>> = RefCell::default()
}

// This macro is basically eprintln but without being captured and
// hidden by the test runner.
macro_rules! elog {
    () => (write!(std::io::stderr()).ok());
    ($($arg:tt)*) => ({
        writeln!(std::io::stderr(), $($arg)*).ok();
    })
}

/// Special marker to use an automatic name.
///
/// This can be passed as a snapshot name in a macro to explicitly tell
/// insta to use the automatic name.  This is useful in ambiguous syntax
/// situations.
#[derive(Debug)]
pub struct AutoName;

impl From<AutoName> for ReferenceValue<'static> {
    fn from(_value: AutoName) -> ReferenceValue<'static> {
        ReferenceValue::Named(None)
    }
}

impl From<Option<String>> for ReferenceValue<'static> {
    fn from(value: Option<String>) -> ReferenceValue<'static> {
        ReferenceValue::Named(value.map(Cow::Owned))
    }
}

impl From<String> for ReferenceValue<'static> {
    fn from(value: String) -> ReferenceValue<'static> {
        ReferenceValue::Named(Some(Cow::Owned(value)))
    }
}

impl<'a> From<Option<&'a str>> for ReferenceValue<'a> {
    fn from(value: Option<&'a str>) -> ReferenceValue<'a> {
        ReferenceValue::Named(value.map(Cow::Borrowed))
    }
}

impl<'a> From<&'a str> for ReferenceValue<'a> {
    fn from(value: &'a str) -> ReferenceValue<'a> {
        ReferenceValue::Named(Some(Cow::Borrowed(value)))
    }
}

pub enum ReferenceValue<'a> {
    Named(Option<Cow<'a, str>>),
    Inline(&'a str),
}

fn is_doctest(function_name: &str) -> bool {
    function_name.starts_with("rust_out::main::_doctest")
}

fn detect_snapshot_name(
    function_name: &str,
    module_path: &str,
    inline: bool,
    is_doctest: bool,
) -> Result<String, &'static str> {
    let mut name = function_name;

    // simplify doctest names
    if is_doctest && !inline {
        panic!("Cannot determine reliable names for snapshot in doctests.  Please use explicit names instead.");
    }

    // clean test name first
    name = name.rsplit("::").next().unwrap();
    let mut test_prefixed = false;
    if name.starts_with("test_") {
        name = &name[5..];
        test_prefixed = true;
    }

    // next check if we need to add a suffix
    let name = add_suffix_to_snapshot_name(Cow::Borrowed(name));
    let key = format!("{}::{}", module_path.replace("::", "__"), name);

    // because fn foo and fn test_foo end up with the same snapshot name we
    // make sure we detect this here and raise an error.
    let mut name_clash_detection = TEST_NAME_CLASH_DETECTION
        .lock()
        .unwrap_or_else(|x| x.into_inner());
    match name_clash_detection.get(&key) {
        None => {
            name_clash_detection.insert(key.clone(), test_prefixed);
        }
        Some(&was_test_prefixed) => {
            if was_test_prefixed != test_prefixed {
                panic!(
                    "Insta snapshot name clash detected between '{}' \
                     and 'test_{}' in '{}'. Rename one function.",
                    name, name, module_path
                );
            }
        }
    }

    // The rest of the code just deals with duplicates, which we in some
    // cases do not want to guard against.
    if allow_duplicates() {
        return Ok(name.to_string());
    }

    // if the snapshot name clashes we need to increment a counter.
    // we really do not care about poisoning here.
    let mut counters = TEST_NAME_COUNTERS.lock().unwrap_or_else(|x| x.into_inner());
    let test_idx = counters.get(&key).cloned().unwrap_or(0) + 1;
    let rv = if test_idx == 1 {
        name.to_string()
    } else {
        format!("{}-{}", name, test_idx)
    };
    counters.insert(key, test_idx);

    Ok(rv)
}

/// If there is a suffix on the settings, append it to the snapshot name.
fn add_suffix_to_snapshot_name(name: Cow<'_, str>) -> Cow<'_, str> {
    Settings::with(|settings| {
        settings
            .snapshot_suffix()
            .map(|suffix| Cow::Owned(format!("{}@{}", name, suffix)))
            .unwrap_or_else(|| name)
    })
}

fn get_snapshot_filename(
    module_path: &str,
    assertion_file: &str,
    snapshot_name: &str,
    cargo_workspace: &Path,
    base: &str,
    is_doctest: bool,
) -> PathBuf {
    let root = Path::new(cargo_workspace);
    let base = Path::new(base);
    Settings::with(|settings| {
        root.join(base.parent().unwrap())
            .join(settings.snapshot_path())
            .join({
                use std::fmt::Write;
                let mut f = String::new();
                if settings.prepend_module_to_snapshot() {
                    if is_doctest {
                        write!(
                            &mut f,
                            "doctest_{}__",
                            Path::new(assertion_file)
                                .file_name()
                                .unwrap()
                                .to_string_lossy()
                                .replace('.', "_")
                        )
                        .unwrap();
                    } else {
                        write!(&mut f, "{}__", module_path.replace("::", "__")).unwrap();
                    }
                }
                write!(
                    &mut f,
                    "{}.snap",
                    snapshot_name.replace(&['/', '\\'][..], "__")
                )
                .unwrap();
                f
            })
    })
}

#[derive(Debug)]
struct SnapshotAssertionContext<'a> {
    tool_config: Arc<ToolConfig>,
    cargo_workspace: Arc<PathBuf>,
    module_path: &'a str,
    snapshot_name: Option<Cow<'a, str>>,
    snapshot_file: Option<PathBuf>,
    duplication_key: Option<String>,
    old_snapshot: Option<Snapshot>,
    pending_snapshots_path: Option<PathBuf>,
    assertion_file: &'a str,
    assertion_line: u32,
    is_doctest: bool,
}

impl<'a> SnapshotAssertionContext<'a> {
    fn prepare(
        refval: ReferenceValue<'a>,
        manifest_dir: &'a str,
        function_name: &'a str,
        module_path: &'a str,
        assertion_file: &'a str,
        assertion_line: u32,
    ) -> Result<SnapshotAssertionContext<'a>, Box<dyn Error>> {
        let tool_config = get_tool_config(manifest_dir);
        let cargo_workspace = get_cargo_workspace(manifest_dir);
        let snapshot_name;
        let mut duplication_key = None;
        let mut snapshot_file = None;
        let mut old_snapshot = None;
        let mut pending_snapshots_path = None;
        let is_doctest = is_doctest(function_name);

        match refval {
            ReferenceValue::Named(name) => {
                let name = match name {
                    Some(name) => add_suffix_to_snapshot_name(name),
                    None => detect_snapshot_name(function_name, module_path, false, is_doctest)
                        .unwrap()
                        .into(),
                };
                if allow_duplicates() {
                    duplication_key = Some(format!("named:{}|{}", module_path, name));
                }
                let file = get_snapshot_filename(
                    module_path,
                    assertion_file,
                    &name,
                    &cargo_workspace,
                    assertion_file,
                    is_doctest,
                );
                if fs::metadata(&file).is_ok() {
                    old_snapshot = Some(Snapshot::from_file(&file)?);
                }
                snapshot_name = Some(name);
                snapshot_file = Some(file);
            }
            ReferenceValue::Inline(contents) => {
                if allow_duplicates() {
                    duplication_key = Some(format!(
                        "inline:{}|{}|{}",
                        function_name, assertion_file, assertion_line
                    ));
                } else {
                    prevent_inline_duplicate(function_name, assertion_file, assertion_line);
                }
                snapshot_name = detect_snapshot_name(function_name, module_path, true, is_doctest)
                    .ok()
                    .map(Cow::Owned);
                let mut pending_file = cargo_workspace.join(assertion_file);
                pending_file.set_file_name(format!(
                    ".{}.pending-snap",
                    pending_file
                        .file_name()
                        .expect("no filename")
                        .to_str()
                        .expect("non unicode filename")
                ));
                pending_snapshots_path = Some(pending_file);
                old_snapshot = Some(Snapshot::from_components(
                    module_path.replace("::", "__"),
                    None,
                    MetaData::default(),
                    SnapshotContents::from_inline(contents),
                ));
            }
        };

        Ok(SnapshotAssertionContext {
            tool_config,
            cargo_workspace,
            module_path,
            snapshot_name,
            snapshot_file,
            old_snapshot,
            pending_snapshots_path,
            assertion_file,
            assertion_line,
            duplication_key,
            is_doctest,
        })
    }

    /// Given a path returns the local path within the workspace.
    pub fn localize_path(&self, p: &Path) -> Option<PathBuf> {
        let workspace = self.cargo_workspace.canonicalize().ok()?;
        let p = self.cargo_workspace.join(p).canonicalize().ok()?;
        p.strip_prefix(&workspace).ok().map(|x| x.to_path_buf())
    }

    /// Creates the new snapshot from input values.
    pub fn new_snapshot(&self, contents: SnapshotContents, expr: &str) -> Snapshot {
        Snapshot::from_components(
            self.module_path.replace("::", "__"),
            self.snapshot_name.as_ref().map(|x| x.to_string()),
            Settings::with(|settings| MetaData {
                source: Some(path_to_storage(Path::new(self.assertion_file))),
                assertion_line: Some(self.assertion_line),
                description: settings.description().map(Into::into),
                expression: if settings.omit_expression() {
                    None
                } else {
                    Some(expr.to_string())
                },
                info: settings.info().map(ToOwned::to_owned),
                input_file: settings
                    .input_file()
                    .and_then(|x| self.localize_path(x))
                    .map(|x| path_to_storage(&x)),
            }),
            contents,
        )
    }

    /// Cleanup logic for passing snapshots.
    pub fn cleanup_passing(&self) -> Result<(), Box<dyn Error>> {
        // let's just make sure there are no more pending files lingering
        // around.
        if let Some(ref snapshot_file) = self.snapshot_file {
            let mut snapshot_file = snapshot_file.clone();
            snapshot_file.set_extension("snap.new");
            fs::remove_file(snapshot_file).ok();
        }

        // and add a null pending snapshot to a pending snapshot file if needed
        if let Some(ref pending_snapshots) = self.pending_snapshots_path {
            if fs::metadata(pending_snapshots).is_ok() {
                PendingInlineSnapshot::new(None, None, self.assertion_line)
                    .save(pending_snapshots)?;
            }
        }
        Ok(())
    }

    /// Writes the changes of the snapshot back.
    pub fn update_snapshot(
        &self,
        new_snapshot: Snapshot,
    ) -> Result<SnapshotUpdateBehavior, Box<dyn Error>> {
        let unseen = self
            .snapshot_file
            .as_ref()
            .map_or(false, |x| fs::metadata(x).is_ok());
        let should_print = self.tool_config.output_behavior() != OutputBehavior::Nothing;
        let snapshot_update = snapshot_update_behavior(&self.tool_config, unseen);

        match snapshot_update {
            SnapshotUpdateBehavior::InPlace => {
                if let Some(ref snapshot_file) = self.snapshot_file {
                    let saved = new_snapshot.save(snapshot_file)?;
                    if should_print && saved {
                        elog!(
                            "{} {}",
                            if unseen {
                                style("created previously unseen snapshot").green()
                            } else {
                                style("updated snapshot").green()
                            },
                            style(snapshot_file.display()).cyan().underlined(),
                        );
                    }
                } else if should_print {
                    elog!(
                        "{}",
                        style(
                            "error: cannot update inline snapshots in-place \
                        (https://github.com/mitsuhiko/insta/issues/272)"
                        )
                        .red()
                        .bold(),
                    );
                }
            }
            SnapshotUpdateBehavior::NewFile => {
                if let Some(ref snapshot_file) = self.snapshot_file {
                    if let Some(new_path) = new_snapshot.save_new(snapshot_file)? {
                        if should_print {
                            elog!(
                                "{} {}",
                                style("stored new snapshot").green(),
                                style(new_path.display()).cyan().underlined(),
                            );
                        }
                    }
                } else if self.is_doctest {
                    if should_print {
                        elog!(
                            "{}",
                            style("warning: cannot update inline snapshots in doctests")
                                .red()
                                .bold(),
                        );
                    }

                // special case for pending inline snapshots.  Here we really only want
                // to write the contents if the snapshot contents changed as the metadata
                // is not retained for inline snapshots.  This used to have different
                // behavior in the past where we did indeed want to rewrite the snapshots
                // entirely since we used to change the canonical snapshot format, but now
                // this is significantly less likely to happen and seeing hundreds of unchanged
                // inline snapshots in the review screen is not a lot of fun.
                } else if self
                    .old_snapshot
                    .as_ref()
                    .map_or(true, |x| x.contents() != new_snapshot.contents())
                {
                    PendingInlineSnapshot::new(
                        Some(new_snapshot),
                        self.old_snapshot.clone(),
                        self.assertion_line,
                    )
                    .save(self.pending_snapshots_path.as_ref().unwrap())?;
                }
            }
            SnapshotUpdateBehavior::NoUpdate => {}
        }

        Ok(snapshot_update)
    }
}

fn prevent_inline_duplicate(function_name: &str, assertion_file: &str, assertion_line: u32) {
    let key = format!("{}|{}|{}", function_name, assertion_file, assertion_line);
    let mut set = INLINE_DUPLICATES.lock().unwrap();
    if set.contains(&key) {
        // drop the lock so we don't poison it
        drop(set);
        panic!(
            "Insta does not allow inline snapshot assertions in loops. \
            Wrap your assertions in allow_duplicates! to change this."
        );
    }
    set.insert(key);
}

/// This prints the information about the snapshot
fn print_snapshot_info(ctx: &SnapshotAssertionContext, new_snapshot: &Snapshot) {
    let mut printer = SnapshotPrinter::new(
        ctx.cargo_workspace.as_path(),
        ctx.old_snapshot.as_ref(),
        new_snapshot,
    );
    printer.set_line(Some(ctx.assertion_line));
    printer.set_snapshot_file(ctx.snapshot_file.as_deref());
    printer.set_title(Some("Snapshot Summary"));
    printer.set_show_info(true);
    match ctx.tool_config.output_behavior() {
        OutputBehavior::Summary => {
            printer.print();
        }
        OutputBehavior::Diff => {
            printer.set_show_diff(true);
            printer.print();
        }
        _ => {}
    }
}

#[cfg(feature = "glob")]
macro_rules! print_or_panic {
    ($fail_fast:expr, $($tokens:tt)*) => {{
        if (!$fail_fast) {
            eprintln!($($tokens)*);
            eprintln!();
        } else {
            panic!($($tokens)*);
        }
    }}
}

/// Finalizes the assertion based on the update result.
fn finalize_assertion(ctx: &SnapshotAssertionContext, update_result: SnapshotUpdateBehavior) {
    // if we are in glob mode, we want to adjust the finalization
    // so that we do not show the hints immediately.
    let fail_fast = {
        #[cfg(feature = "glob")]
        {
            if let Some(top) = crate::glob::GLOB_STACK.lock().unwrap().last() {
                top.fail_fast
            } else {
                true
            }
        }
        #[cfg(not(feature = "glob"))]
        {
            true
        }
    };

    if fail_fast
        && update_result == SnapshotUpdateBehavior::NewFile
        && ctx.tool_config.output_behavior() != OutputBehavior::Nothing
        && !ctx.is_doctest
    {
        println!(
            "{hint}",
            hint = style("To update snapshots run `cargo insta review`").dim(),
        );
    }

    if update_result != SnapshotUpdateBehavior::InPlace && !ctx.tool_config.force_pass() {
        if fail_fast && ctx.tool_config.output_behavior() != OutputBehavior::Nothing {
            println!(
                "{hint}",
                hint = style(
                    "Stopped on the first failure. Run `cargo insta test` to run all snapshots."
                )
                .dim(),
            );
        }

        // if we are in glob mode, count the failures and print the
        // errors instead of panicking.  The glob will then panic at
        // the end.
        #[cfg(feature = "glob")]
        {
            let mut stack = crate::glob::GLOB_STACK.lock().unwrap();
            if let Some(glob_collector) = stack.last_mut() {
                glob_collector.failed += 1;
                if update_result == SnapshotUpdateBehavior::NewFile
                    && ctx.tool_config.output_behavior() != OutputBehavior::Nothing
                {
                    glob_collector.show_insta_hint = true;
                }

                print_or_panic!(
                    fail_fast,
                    "snapshot assertion from glob for '{}' failed in line {}",
                    ctx.snapshot_name.as_deref().unwrap_or("unnamed snapshot"),
                    ctx.assertion_line
                );
                return;
            }
        }

        panic!(
            "snapshot assertion for '{}' failed in line {}",
            ctx.snapshot_name.as_deref().unwrap_or("unnamed snapshot"),
            ctx.assertion_line
        );
    }
}

fn record_snapshot_duplicate(
    results: &mut BTreeMap<String, Snapshot>,
    snapshot: &Snapshot,
    ctx: &SnapshotAssertionContext,
) {
    let key = ctx.duplication_key.as_deref().unwrap();
    if let Some(prev_snapshot) = results.get(key) {
        if prev_snapshot.contents() != snapshot.contents() {
            println!("Snapshots in allow-duplicates block do not match.");
            let mut printer =
                SnapshotPrinter::new(ctx.cargo_workspace.as_path(), Some(prev_snapshot), snapshot);
            printer.set_line(Some(ctx.assertion_line));
            printer.set_snapshot_file(ctx.snapshot_file.as_deref());
            printer.set_title(Some("Differences in Block"));
            printer.set_snapshot_hints("previous assertion", "current assertion");
            if ctx.tool_config.output_behavior() == OutputBehavior::Diff {
                printer.set_show_diff(true);
            }
            printer.print();
            panic!(
                "snapshot assertion for '{}' failed in line {}. Result \
                    does not match previous snapshot in allow-duplicates block.",
                ctx.snapshot_name.as_deref().unwrap_or("unnamed snapshot"),
                ctx.assertion_line
            );
        }
    } else {
        results.insert(key.to_string(), snapshot.clone());
    }
}

/// Do we allow recording of duplicates?
fn allow_duplicates() -> bool {
    RECORDED_DUPLICATES.with(|x| !x.borrow().is_empty())
}

/// Helper function to support perfect duplicate detection.
pub fn with_allow_duplicates<R, F>(f: F) -> R
where
    F: FnOnce() -> R,
{
    RECORDED_DUPLICATES.with(|x| x.borrow_mut().push(BTreeMap::new()));
    let rv = std::panic::catch_unwind(std::panic::AssertUnwindSafe(f));
    RECORDED_DUPLICATES.with(|x| x.borrow_mut().pop().unwrap());
    match rv {
        Ok(rv) => rv,
        Err(payload) => std::panic::resume_unwind(payload),
    }
}

/// This function is invoked from the macros to run the main assertion logic.
///
/// This will create the assertion context, run the main logic to assert
/// on snapshots and write changes to the pending snapshot files.  It will
/// also print the necessary bits of information to the output and fail the
/// assertion with a panic if needed.
#[allow(clippy::too_many_arguments)]
pub fn assert_snapshot(
    refval: ReferenceValue<'_>,
    new_snapshot_value: &str,
    manifest_dir: &str,
    function_name: &str,
    module_path: &str,
    assertion_file: &str,
    assertion_line: u32,
    expr: &str,
) -> Result<(), Box<dyn Error>> {
    let ctx = SnapshotAssertionContext::prepare(
        refval,
        manifest_dir,
        function_name,
        module_path,
        assertion_file,
        assertion_line,
    )?;
    let tool_config = get_tool_config(manifest_dir);

    // apply filters if they are available
    #[cfg(feature = "filters")]
    let new_snapshot_value =
        Settings::with(|settings| settings.filters().apply_to(new_snapshot_value));

    let new_snapshot = ctx.new_snapshot(new_snapshot_value.into(), expr);

    // memoize the snapshot file if requested.
    if let Some(ref snapshot_file) = ctx.snapshot_file {
        memoize_snapshot_file(snapshot_file);
    }

    // If we allow assertion with duplicates, we record the duplicate now.  This will
    // in itself fail the assertion if the previous visit of the same assertion macro
    // did not yield the same result.
    RECORDED_DUPLICATES.with(|x| {
        if let Some(results) = x.borrow_mut().last_mut() {
            record_snapshot_duplicate(results, &new_snapshot, &ctx);
        }
    });

    let pass = ctx
        .old_snapshot
        .as_ref()
        .map(|x| {
            if tool_config.require_full_match() {
                x.matches_fully(&new_snapshot)
            } else {
                x.matches(&new_snapshot)
            }
        })
        .unwrap_or(false);

    if pass {
        ctx.cleanup_passing()?;

        if tool_config.force_update_snapshots() {
            ctx.update_snapshot(new_snapshot)?;
        }
    // otherwise print information and update snapshots.
    } else {
        print_snapshot_info(&ctx, &new_snapshot);
        let update_result = ctx.update_snapshot(new_snapshot)?;
        finalize_assertion(&ctx, update_result);
    }

    Ok(())
}

/// Test snapshots in doctests.
///
/// ```
/// insta::assert_debug_snapshot!("named", vec![1, 2, 3, 4, 5]);
/// ```
///
/// ```should_panic
/// insta::assert_debug_snapshot!(vec![1, 2, 3, 4, 5]);
/// ```
///
/// ```
/// let some_string = "Coucou je suis un joli bug";
/// insta::assert_snapshot!(some_string, @"Coucou je suis un joli bug");
/// ```
///
/// ```
/// let some_string = "Coucou je suis un joli bug";
/// insta::assert_snapshot!(some_string, @"Coucou je suis un joli bug");
/// ```
const _DOCTEST1: bool = false;
