use std::{borrow::Borrow, path::Path};

use gix_object::bstr::{BStr, BString, ByteSlice};

use crate::{bstr::ByteVec, name::is_pseudo_ref, Category, FullName, FullNameRef, Namespace, PartialNameRef};

impl TryFrom<&str> for FullName {
    type Error = gix_validate::reference::name::Error;

    fn try_from(value: &str) -> Result<Self, Self::Error> {
        Ok(FullName(
            gix_validate::reference::name(value.as_bytes().as_bstr())?.into(),
        ))
    }
}

impl TryFrom<String> for FullName {
    type Error = gix_validate::reference::name::Error;

    fn try_from(value: String) -> Result<Self, Self::Error> {
        gix_validate::reference::name(value.as_bytes().as_bstr())?;
        Ok(FullName(value.into()))
    }
}

impl TryFrom<&BStr> for FullName {
    type Error = gix_validate::reference::name::Error;

    fn try_from(value: &BStr) -> Result<Self, Self::Error> {
        Ok(FullName(gix_validate::reference::name(value)?.into()))
    }
}

impl TryFrom<BString> for FullName {
    type Error = gix_validate::reference::name::Error;

    fn try_from(value: BString) -> Result<Self, Self::Error> {
        gix_validate::reference::name(value.as_ref())?;
        Ok(FullName(value))
    }
}

impl TryFrom<&BString> for FullName {
    type Error = gix_validate::reference::name::Error;

    fn try_from(value: &BString) -> Result<Self, Self::Error> {
        gix_validate::reference::name(value.as_ref())?;
        Ok(FullName(value.clone()))
    }
}

impl From<FullName> for BString {
    fn from(name: FullName) -> Self {
        name.0
    }
}

impl<'a> From<&'a FullNameRef> for &'a BStr {
    fn from(name: &'a FullNameRef) -> Self {
        &name.0
    }
}

impl<'a> From<&'a FullNameRef> for FullName {
    fn from(value: &'a FullNameRef) -> Self {
        FullName(value.as_bstr().into())
    }
}

impl std::fmt::Display for FullName {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        std::fmt::Display::fmt(&self.0, f)
    }
}

impl FullNameRef {
    /// Interpret this fully qualified reference name as partial name.
    pub fn as_partial_name(&self) -> &PartialNameRef {
        PartialNameRef::new_unchecked(self.0.as_bstr())
    }

    /// Convert this name into the relative path identifying the reference location.
    pub fn to_path(&self) -> &Path {
        gix_path::from_byte_slice(&self.0)
    }

    /// Return ourselves as byte string which is a valid refname
    pub fn as_bstr(&self) -> &BStr {
        &self.0
    }

    /// Strip well-known prefixes from the name and return it.
    ///
    /// If there is no such prefix, the original name is returned.
    pub fn shorten(&self) -> &BStr {
        self.category_and_short_name()
            .map_or_else(|| self.0.as_bstr(), |(_, short)| short)
    }

    /// Classify this name, or return `None` if it's unclassified.
    pub fn category(&self) -> Option<Category<'_>> {
        self.category_and_short_name().map(|(cat, _)| cat)
    }

    /// Classify this name, or return `None` if it's unclassified. If `Some`,
    /// the shortened name is returned as well.
    pub fn category_and_short_name(&self) -> Option<(Category<'_>, &BStr)> {
        let name = self.0.as_bstr();
        for category in &[Category::Tag, Category::LocalBranch, Category::RemoteBranch] {
            if let Some(shortened) = name.strip_prefix(category.prefix().as_bytes()) {
                return Some((*category, shortened.as_bstr()));
            }
        }

        for category in &[
            Category::Note,
            Category::Bisect,
            Category::WorktreePrivate,
            Category::Rewritten,
        ] {
            if name.starts_with(category.prefix().as_ref()) {
                return Some((
                    *category,
                    name.strip_prefix(b"refs/")
                        .expect("we checked for refs/* above")
                        .as_bstr(),
                ));
            }
        }

        if is_pseudo_ref(name) {
            Some((Category::PseudoRef, name))
        } else if let Some(shortened) = name.strip_prefix(Category::MainPseudoRef.prefix().as_bytes()) {
            if shortened.starts_with_str("refs/") {
                (Category::MainRef, shortened.as_bstr()).into()
            } else {
                is_pseudo_ref(shortened.into()).then(|| (Category::MainPseudoRef, shortened.as_bstr()))
            }
        } else if let Some(shortened_with_worktree_name) =
            name.strip_prefix(Category::LinkedPseudoRef { name: "".into() }.prefix().as_bytes())
        {
            let (name, shortened) = shortened_with_worktree_name.find_byte(b'/').map(|pos| {
                (
                    shortened_with_worktree_name[..pos].as_bstr(),
                    shortened_with_worktree_name[pos + 1..].as_bstr(),
                )
            })?;
            if shortened.starts_with_str("refs/") {
                (Category::LinkedRef { name }, shortened.as_bstr()).into()
            } else {
                is_pseudo_ref(shortened).then(|| (Category::LinkedPseudoRef { name }, shortened.as_bstr()))
            }
        } else {
            None
        }
    }
}

impl FullName {
    /// Convert this name into the relative path, lossily, identifying the reference location relative to a repository
    pub fn to_path(&self) -> &Path {
        gix_path::from_byte_slice(&self.0)
    }

    /// Dissolve this instance and return the buffer.
    pub fn into_inner(self) -> BString {
        self.0
    }

    /// Return ourselves as byte string which is a valid refname
    pub fn as_bstr(&self) -> &BStr {
        self.0.as_bstr()
    }

    /// Modify ourself so that we use `namespace` as prefix, if it is not yet in the `namespace`
    pub fn prefix_namespace(&mut self, namespace: &Namespace) -> &mut Self {
        if !self.0.starts_with_str(&namespace.0) {
            self.0.insert_str(0, &namespace.0);
        }
        self
    }

    /// Strip the given `namespace` off the beginning of this name, if it is in this namespace.
    pub fn strip_namespace(&mut self, namespace: &Namespace) -> &mut Self {
        if self.0.starts_with_str(&namespace.0) {
            let prev_len = self.0.len();
            self.0.copy_within(namespace.0.len().., 0);
            self.0.resize(prev_len - namespace.0.len(), 0);
        }
        self
    }

    /// Strip well-known prefixes from the name and return it.
    ///
    /// If there is no such prefix, the original name is returned.
    pub fn shorten(&self) -> &BStr {
        self.as_ref().shorten()
    }

    /// Classify this name, or return `None` if it's unclassified.
    pub fn category(&self) -> Option<crate::Category<'_>> {
        self.as_ref().category()
    }

    /// Classify this name, or return `None` if it's unclassified. If `Some`,
    /// the shortened name is returned as well.
    pub fn category_and_short_name(&self) -> Option<(crate::Category<'_>, &BStr)> {
        self.as_ref().category_and_short_name()
    }
}

impl FullNameRef {
    /// Return the file name portion of a full name, for instance `main` if the
    /// full name was `refs/heads/main`.
    pub fn file_name(&self) -> &BStr {
        self.0.rsplitn(2, |b| *b == b'/').next().expect("valid ref").as_bstr()
    }
}

impl Borrow<FullNameRef> for FullName {
    #[inline]
    fn borrow(&self) -> &FullNameRef {
        FullNameRef::new_unchecked(self.0.as_bstr())
    }
}

impl AsRef<FullNameRef> for FullName {
    fn as_ref(&self) -> &FullNameRef {
        self.borrow()
    }
}

impl ToOwned for FullNameRef {
    type Owned = FullName;

    fn to_owned(&self) -> Self::Owned {
        FullName(self.0.to_owned())
    }
}
