use bstr::{BStr, BString};

use crate::{protocol, protocol::Context, Program};

/// A list of helper programs to run in order to obtain credentials.
#[allow(dead_code)]
#[derive(Debug)]
pub struct Cascade {
    /// The programs to run in order to obtain credentials
    pub programs: Vec<Program>,
    /// If true, stderr is enabled when `programs` are run, which is the default.
    pub stderr: bool,
    /// If true, http(s) urls will take their path portion into account when obtaining credentials. Default is false.
    /// Other protocols like ssh will always use the path portion.
    pub use_http_path: bool,
    /// If true, default false, when getting credentials, we will set a bogus password to only obtain the user name.
    /// Storage and cancellation work the same, but without a password set.
    pub query_user_only: bool,
}

/// The outcome of the credentials helper [invocation][crate::helper::invoke()].
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Outcome {
    /// The username to use in the identity, if set.
    pub username: Option<String>,
    /// The password to use in the identity, if set.
    pub password: Option<String>,
    /// If set, the helper asked to stop the entire process, whether the identity is complete or not.
    pub quit: bool,
    /// A handle to the action to perform next in another call to [`helper::invoke()`][crate::helper::invoke()].
    pub next: NextAction,
}

impl Outcome {
    /// Try to fetch username _and_ password to form an identity. This will fail if one of them is not set.
    ///
    /// This does nothing if only one of the fields is set, or consume both.
    pub fn consume_identity(&mut self) -> Option<gix_sec::identity::Account> {
        if self.username.is_none() || self.password.is_none() {
            return None;
        }
        self.username
            .take()
            .zip(self.password.take())
            .map(|(username, password)| gix_sec::identity::Account { username, password })
    }
}

/// The Result type used in [`invoke()`][crate::helper::invoke()].
pub type Result = std::result::Result<Option<Outcome>, Error>;

/// The error used in the [credentials helper invocation][crate::helper::invoke()].
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum Error {
    #[error(transparent)]
    ContextDecode(#[from] protocol::context::decode::Error),
    #[error("An IO error occurred while communicating to the credentials helper")]
    Io(#[from] std::io::Error),
    #[error(transparent)]
    CredentialsHelperFailed { source: std::io::Error },
}

/// The action to perform by the credentials [helper][`crate::helper::invoke()`].
#[derive(Clone, Debug)]
pub enum Action {
    /// Provide credentials using the given repository context, which must include the repository url.
    Get(Context),
    /// Approve the credentials as identified by the previous input provided as `BString`, containing information from [`Context`].
    Store(BString),
    /// Reject the credentials as identified by the previous input provided as `BString`. containing information from [`Context`].
    Erase(BString),
}

/// Initialization
impl Action {
    /// Create a `Get` action with context containing the given URL.
    /// Note that this creates an `Action` suitable for the credential helper cascade only.
    pub fn get_for_url(url: impl Into<BString>) -> Action {
        Action::Get(Context {
            url: Some(url.into()),
            ..Default::default()
        })
    }
}

/// Access
impl Action {
    /// Return the payload of store or erase actions.
    pub fn payload(&self) -> Option<&BStr> {
        use bstr::ByteSlice;
        match self {
            Action::Get(_) => None,
            Action::Store(p) | Action::Erase(p) => Some(p.as_bstr()),
        }
    }
    /// Return the context of a get operation, or `None`.
    ///
    /// The opposite of [`payload`][Action::payload()].
    pub fn context(&self) -> Option<&Context> {
        match self {
            Action::Get(ctx) => Some(ctx),
            Action::Erase(_) | Action::Store(_) => None,
        }
    }

    /// Return the mutable context of a get operation, or `None`.
    pub fn context_mut(&mut self) -> Option<&mut Context> {
        match self {
            Action::Get(ctx) => Some(ctx),
            Action::Erase(_) | Action::Store(_) => None,
        }
    }

    /// Returns true if this action expects output from the helper.
    pub fn expects_output(&self) -> bool {
        matches!(self, Action::Get(_))
    }

    /// The name of the argument to describe this action. If `is_external` is true, the target program is
    /// a custom credentials helper, not a built-in one.
    pub fn as_arg(&self, is_external: bool) -> &str {
        match self {
            Action::Get(_) if is_external => "get",
            Action::Get(_) => "fill",
            Action::Store(_) if is_external => "store",
            Action::Store(_) => "approve",
            Action::Erase(_) if is_external => "erase",
            Action::Erase(_) => "reject",
        }
    }
}

/// A handle to [store][NextAction::store()] or [erase][NextAction::erase()] the outcome of the initial action.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct NextAction {
    previous_output: BString,
}

impl TryFrom<&NextAction> for Context {
    type Error = protocol::context::decode::Error;

    fn try_from(value: &NextAction) -> std::result::Result<Self, Self::Error> {
        Context::from_bytes(value.previous_output.as_ref())
    }
}

impl From<Context> for NextAction {
    fn from(ctx: Context) -> Self {
        let mut buf = Vec::<u8>::new();
        ctx.write_to(&mut buf).expect("cannot fail");
        NextAction {
            previous_output: buf.into(),
        }
    }
}

impl NextAction {
    /// Approve the result of the previous [Action] and store for lookup.
    pub fn store(self) -> Action {
        Action::Store(self.previous_output)
    }
    /// Reject the result of the previous [Action] and erase it as to not be returned when being looked up.
    pub fn erase(self) -> Action {
        Action::Erase(self.previous_output)
    }
}

mod cascade;
pub(crate) mod invoke;

pub use invoke::invoke;
