use std::path;
use std::process;

use crate::error::{CargoError, CargoResult};
use crate::format;
use crate::msg::CommandMessages;

/// The `test` subcommand (emulated).
///
/// Created via [`CargoBuild::run_tests`].
///
/// Benefits over spawning `cargo test`:
/// - Able to cache binary path, avoiding cargo overhead.
/// - Independent of CWD.
/// - stdout/stderr are clean of `cargo test` output.
///
/// Required feature: `test_unstable` since the format parsed is unstable.
///
/// Relevant features
/// - `print` for logged output to be printed instead, generally for test writing.
///
/// # Example
///
/// ```rust
/// # let target_dir = tempfile::TempDir::new().unwrap();
/// let run = escargot::CargoBuild::new()
///     .test("test")
///     .manifest_path("tests/testsuite/fixtures/test/Cargo.toml")
///     .target_dir(target_dir.path())
///     .run_tests().unwrap()
///     .next().unwrap().unwrap();
/// println!("artifact={}", run.path().display());
/// ```
///
/// [`CargoBuild::run_tests`]: crate::CargoBuild::run_tests()
pub struct CargoTest {
    bin_path: path::PathBuf,
    kind: String,
    name: String,
}

impl CargoTest {
    pub(crate) fn with_messages(
        msgs: CommandMessages,
    ) -> impl Iterator<Item = Result<Self, CargoError>> {
        extract_binary_paths(msgs)
    }

    /// The `name` of test
    ///
    /// Used to offer filtering or displays.
    ///
    /// # Example
    ///
    /// ```rust
    /// # let target_dir = tempfile::TempDir::new().unwrap();
    /// let run: Result<Vec<_>, _> = escargot::CargoBuild::new()
    ///     .tests()
    ///     .current_release()
    ///     .current_target()
    ///     .manifest_path("tests/testsuite/fixtures/test/Cargo.toml")
    ///     .target_dir(target_dir.path())
    ///     .run_tests()
    ///     .unwrap()
    ///     .collect();
    /// let run = run.unwrap();
    /// let mut names: Vec<_> = run.iter().map(|r| r.name()).collect();
    /// names.sort_unstable();
    /// assert_eq!(names, ["test", "test_fixture", "test_fixture"]);
    /// ```
    pub fn name(&self) -> &str {
        self.name.as_str()
    }

    /// The `kind` of test
    ///
    /// Used to distinguish between integration tests (`test`) and unit tests (`bin`, `lib`).
    ///
    /// # Example
    ///
    /// ```rust
    /// # let target_dir = tempfile::TempDir::new().unwrap();
    /// let run: Result<Vec<_>, _> = escargot::CargoBuild::new()
    ///     .tests()
    ///     .current_release()
    ///     .current_target()
    ///     .manifest_path("tests/testsuite/fixtures/test/Cargo.toml")
    ///     .target_dir(target_dir.path())
    ///     .run_tests()
    ///     .unwrap()
    ///     .collect();
    /// let run = run.unwrap();
    /// let mut kinds: Vec<_> = run.iter().map(|r| r.kind()).collect();
    /// kinds.sort_unstable();
    /// assert_eq!(kinds, ["bin", "lib", "test"]);
    /// ```
    pub fn kind(&self) -> &str {
        self.kind.as_str()
    }

    /// Path to the specified binary.
    ///
    /// This is to support alternative ways of launching the binary besides [`Command`].
    ///
    /// # Example
    ///
    /// ```rust
    /// # let target_dir = tempfile::TempDir::new().unwrap();
    /// let run: Vec<_> = escargot::CargoBuild::new()
    ///     .tests()
    ///     .current_release()
    ///     .current_target()
    ///     .manifest_path("tests/testsuite/fixtures/test/Cargo.toml")
    ///     .target_dir(target_dir.path())
    ///     .run_tests()
    ///     .unwrap()
    ///     .collect();
    /// assert_eq!(run.len(), 3);
    /// ```
    ///
    /// [`Command`]: std::process::Command
    pub fn path(&self) -> &path::Path {
        &self.bin_path
    }

    /// Run the build artifact.
    pub fn command(&self) -> process::Command {
        let mut cmd = process::Command::new(self.path());
        cmd.arg("-Z").arg("unstable-options").arg("--format=json");
        cmd
    }

    /// Run the configured test, returning test events.
    pub fn exec(&self) -> CargoResult<CommandMessages> {
        CommandMessages::with_command(self.command())
    }
}

fn extract_bin(msg: &format::Message<'_>) -> Option<CargoTest> {
    match msg {
        format::Message::CompilerArtifact(art) => {
            if art.profile.test {
                let bin_path = art
                    .filenames
                    .first()
                    .expect("files must exist")
                    .to_path_buf();
                let kind = art
                    .target
                    .kind
                    .first()
                    .expect("kind must exist")
                    .as_ref()
                    .to_owned();
                let name = art.target.name.as_ref().to_owned();
                Some(CargoTest {
                    bin_path,
                    kind,
                    name,
                })
            } else {
                None
            }
        }
        _ => None,
    }
}

fn transpose<T, E>(r: Result<Option<T>, E>) -> Option<Result<T, E>> {
    match r {
        Ok(Some(x)) => Some(Ok(x)),
        Ok(None) => None,
        Err(e) => Some(Err(e)),
    }
}

fn extract_binary_paths(
    msgs: CommandMessages,
) -> impl Iterator<Item = Result<CargoTest, CargoError>> {
    msgs.filter_map(move |m| {
        let m = m.and_then(|m| {
            let m = m.decode()?;
            format::log_message(&m);
            let p = extract_bin(&m);
            Ok(p)
        });
        transpose(m)
    })
}
