use uuid::Uuid;

use crate::{projects::Project, teams::Team};

#[derive(Clone, Debug, Default)]
pub struct Breadcrumb {
    pub href: String,
    pub label: String,
}

// TODO: This is a very quick, dirty, and awkward approach to storing
// navigation state. It can and should be scrapped and replaced when time
// allows.

#[derive(Clone, Debug, Default)]
pub struct NavState {
    pub base_path: String,
    pub breadcrumbs: Vec<Breadcrumb>,
    pub team_id: Option<Uuid>,
    pub navbar_active_item: String,
}

impl NavState {
    pub fn new() -> Self {
        Self::default()
    }

    pub fn set_base_path(mut self, base_path: &str) -> Self {
        self.base_path = base_path.to_string();
        self
    }

    pub fn push_team(mut self, team: &Team) -> Self {
        self.team_id = Some(team.id.clone());
        self.navbar_active_item = "teams".to_string();
        self.breadcrumbs.push(Breadcrumb {
            href: format!("{}/teams", self.base_path),
            label: "Teams".to_string(),
        });
        self.breadcrumbs.push(Breadcrumb {
            href: format!("{}/teams/{}", self.base_path, team.id.clone().simple()),
            label: team.name.clone(),
        });
        self
    }

    pub fn push_project(mut self, project: &Project) -> Result<Self, anyhow::Error> {
        let team_id = self.team_id.ok_or(anyhow::anyhow!(
            "NavState.push_project() called out of order"
        ))?;
        self.navbar_active_item = "projects".to_string();
        self.breadcrumbs.push(Breadcrumb {
            href: format!("{}/teams/{}/projects", self.base_path, team_id),
            label: "Projects".to_string(),
        });
        self.breadcrumbs.push(Breadcrumb {
            href: format!(
                "{}/teams/{}/projects/{}",
                self.base_path,
                team_id,
                project.id.clone().simple()
            ),
            label: project.name.clone(),
        });
        Ok(self)
    }

    /**
     * Add a breadcrumb with an href treated as a child of the previous
     * breadcrumb's path (or of the base_path if no breadcrumbs exist).
     */
    pub fn push_slug(mut self, breadcrumb: Breadcrumb) -> Self {
        let starting_path = self
            .breadcrumbs
            .iter()
            .last()
            .map(|breadcrumb| breadcrumb.href.clone())
            .unwrap_or(self.base_path.clone());
        self.breadcrumbs.push(Breadcrumb {
            href: format!("{}/{}", starting_path, breadcrumb.href),
            label: breadcrumb.label,
        });
        self
    }

    pub fn set_navbar_active_item(mut self, value: &str) -> Self {
        self.navbar_active_item = value.to_string();
        self
    }
}
