use axum::extract::{Path, State};
use axum::http::StatusCode;
use axum::response::{Html, IntoResponse, Redirect, Response};
use axum::routing::{get, post};
use axum::{Form, Router};
use forage_core::platform::validate_slug;
use forage_core::session::CachedOrg;
use minijinja::context;
use serde::Deserialize;

use super::error_page;
use crate::auth::{self, Session};
use crate::state::AppState;

pub fn router() -> Router<AppState> {
    Router::new()
        .route("/dashboard", get(dashboard))
        .route("/orgs", post(create_org_submit))
        .route("/orgs/{org}/projects", get(projects_list))
        .route("/orgs/{org}/projects/{project}", get(project_detail))
        .route(
            "/orgs/{org}/projects/{project}/releases/{slug}",
            get(artifact_detail),
        )
        .route("/orgs/{org}/releases", get(releases_page))
        .route("/orgs/{org}/destinations", get(destinations_page))
        .route("/orgs/{org}/usage", get(usage))
        .route(
            "/orgs/{org}/settings/members",
            get(members_page).post(add_member_submit),
        )
        .route(
            "/orgs/{org}/settings/members/{user_id}/role",
            post(update_member_role_submit),
        )
        .route(
            "/orgs/{org}/settings/members/{user_id}/remove",
            post(remove_member_submit),
        )
}

fn orgs_context(orgs: &[CachedOrg]) -> Vec<minijinja::Value> {
    orgs.iter()
        .map(|o| context! { name => o.name, role => o.role })
        .collect()
}

#[allow(clippy::result_large_err)]
fn require_org_membership<'a>(
    state: &AppState,
    orgs: &'a [CachedOrg],
    org: &str,
) -> Result<&'a CachedOrg, Response> {
    if !validate_slug(org) {
        return Err(error_page(
            state,
            StatusCode::BAD_REQUEST,
            "Invalid request",
            "Invalid organisation name.",
        ));
    }
    orgs.iter().find(|o| o.name == org).ok_or_else(|| {
        error_page(
            state,
            StatusCode::FORBIDDEN,
            "Access denied",
            "You don't have access to this organisation.",
        )
    })
}

/// Require the user to be an admin or owner of the organisation.
#[allow(clippy::result_large_err)]
fn require_admin(state: &AppState, org: &CachedOrg) -> Result<(), Response> {
    if org.role == "owner" || org.role == "admin" {
        Ok(())
    } else {
        Err(error_page(
            state,
            StatusCode::FORBIDDEN,
            "Access denied",
            "You must be an admin to perform this action.",
        ))
    }
}

// ─── Dashboard ──────────────────────────────────────────────────────

async fn dashboard(
    State(state): State<AppState>,
    session: Session,
) -> Result<Response, Response> {
    let orgs = &session.user.orgs;

    if orgs.is_empty() {
        // No orgs: show onboarding with create org form
        let html = state
            .templates
            .render(
                "pages/onboarding.html.jinja",
                context! {
                    title => "Get Started - Forage",
                    description => "Create your first organisation",
                    user => context! { username => session.user.username },
                    csrf_token => &session.csrf_token,
                    active_tab => "dashboard",
                },
            )
            .map_err(|e| {
                tracing::error!("template error: {e:#}");
                error_page(
                    &state,
                    StatusCode::INTERNAL_SERVER_ERROR,
                    "Something went wrong",
                    "Please try again.",
                )
            })?;
        return Ok(Html(html).into_response());
    }

    // Fetch recent releases for the first org to show the pipeline on dashboard
    let first_org = &orgs[0];
    let projects = state
        .platform_client
        .list_projects(&session.access_token, &first_org.name)
        .await
        .unwrap_or_default();

    let items = fetch_org_artifacts(&state, &session.access_token, &first_org.name, &projects).await;
    let data = build_timeline(items, &first_org.name);

    let html = state
        .templates
        .render(
            "pages/dashboard.html.jinja",
            context! {
                title => "Dashboard - Forage",
                description => "Your Forage dashboard",
                user => context! { username => session.user.username },
                csrf_token => &session.csrf_token,
                current_org => &first_org.name,
                orgs => orgs_context(orgs),
                timeline => data.timeline,
                lanes => data.lanes,
                active_tab => "dashboard",
            },
        )
        .map_err(|e| {
            tracing::error!("template error: {e:#}");
            error_page(
                &state,
                StatusCode::INTERNAL_SERVER_ERROR,
                "Something went wrong",
                "Please try again.",
            )
        })?;

    Ok(Html(html).into_response())
}

// ─── Create organisation ────────────────────────────────────────────

#[derive(Deserialize)]
struct CreateOrgForm {
    name: String,
    _csrf: String,
}

async fn create_org_submit(
    State(state): State<AppState>,
    session: Session,
    Form(form): Form<CreateOrgForm>,
) -> Result<Response, Response> {
    if !auth::validate_csrf(&session, &form._csrf) {
        return Err(error_page(
            &state,
            StatusCode::FORBIDDEN,
            "Invalid request",
            "CSRF validation failed. Please try again.",
        ));
    }

    if !validate_slug(&form.name) {
        // Re-render onboarding/dashboard with error
        let html = state
            .templates
            .render(
                "pages/onboarding.html.jinja",
                context! {
                    title => "Get Started - Forage",
                    description => "Create your first organisation",
                    user => context! { username => session.user.username },
                    csrf_token => &session.csrf_token,
                    active_tab => "dashboard",
                    error => "Invalid organisation name. Use lowercase letters, numbers, and hyphens only.",
                },
            )
            .map_err(|e| {
                tracing::error!("template error: {e:#}");
                error_page(&state, StatusCode::INTERNAL_SERVER_ERROR, "Something went wrong", "Please try again.")
            })?;
        return Ok(Html(html).into_response());
    }

    match state
        .platform_client
        .create_organisation(&session.access_token, &form.name)
        .await
    {
        Ok(org_id) => {
            // Update session with new org
            if let Ok(Some(mut session_data)) = state.sessions.get(&session.session_id).await {
                if let Some(ref mut user) = session_data.user {
                    user.orgs.push(CachedOrg {
                        organisation_id: org_id,
                        name: form.name.clone(),
                        role: "owner".into(),
                    });
                }
                let _ = state
                    .sessions
                    .update(&session.session_id, session_data)
                    .await;
            }
            Ok(Redirect::to(&format!("/orgs/{}/projects", form.name)).into_response())
        }
        Err(e) => {
            tracing::error!("failed to create org: {e}");
            let html = state
                .templates
                .render(
                    "pages/onboarding.html.jinja",
                    context! {
                        title => "Get Started - Forage",
                        description => "Create your first organisation",
                        user => context! { username => session.user.username },
                        csrf_token => &session.csrf_token,
                        active_tab => "dashboard",
                        error => "Could not create organisation. Please try again.",
                    },
                )
                .map_err(|e| {
                    tracing::error!("template error: {e:#}");
                    error_page(&state, StatusCode::INTERNAL_SERVER_ERROR, "Something went wrong", "Please try again.")
                })?;
            Ok(Html(html).into_response())
        }
    }
}

// ─── Projects list ──────────────────────────────────────────────────

async fn projects_list(
    State(state): State<AppState>,
    session: Session,
    Path(org): Path<String>,
) -> Result<Response, Response> {
    let orgs = &session.user.orgs;
    require_org_membership(&state, orgs, &org)?;

    let projects = state
        .platform_client
        .list_projects(&session.access_token, &org)
        .await
        .unwrap_or_default();

    let html = state
        .templates
        .render(
            "pages/projects.html.jinja",
            context! {
                title => format!("{org} - Projects - Forage"),
                description => format!("Projects in {org}"),
                user => context! { username => session.user.username },
                csrf_token => &session.csrf_token,
                current_org => &org,
                orgs => orgs_context(orgs),
                org_name => &org,
                projects => projects,
                active_tab => "projects",
            },
        )
        .map_err(|e| {
            tracing::error!("template error: {e:#}");
            error_page(
                &state,
                StatusCode::INTERNAL_SERVER_ERROR,
                "Something went wrong",
                "Please try again.",
            )
        })?;

    Ok(Html(html).into_response())
}

// ─── Project detail ─────────────────────────────────────────────────

async fn project_detail(
    State(state): State<AppState>,
    session: Session,
    Path((org, project)): Path<(String, String)>,
) -> Result<Response, Response> {
    let orgs = &session.user.orgs;
    require_org_membership(&state, orgs, &org)?;

    if !validate_slug(&project) {
        return Err(error_page(
            &state,
            StatusCode::BAD_REQUEST,
            "Invalid request",
            "Invalid project name.",
        ));
    }

    let artifacts = state
        .platform_client
        .list_artifacts(&session.access_token, &org, &project)
        .await
        .unwrap_or_default();

    let items: Vec<ArtifactWithProject> = artifacts
        .into_iter()
        .map(|a| ArtifactWithProject {
            artifact: a,
            project_name: project.clone(),
        })
        .collect();
    let data = build_timeline(items, &org);

    let html = state
        .templates
        .render(
            "pages/project_detail.html.jinja",
            context! {
                title => format!("{project} - {org} - Forage"),
                description => format!("Project {project} in {org}"),
                user => context! { username => session.user.username },
                csrf_token => &session.csrf_token,
                current_org => &org,
                orgs => orgs_context(orgs),
                org_name => &org,
                project_name => &project,
                active_tab => "projects",
                timeline => data.timeline,
                lanes => data.lanes,
            },
        )
        .map_err(|e| {
            tracing::error!("template error: {e:#}");
            error_page(
                &state,
                StatusCode::INTERNAL_SERVER_ERROR,
                "Something went wrong",
                "Please try again.",
            )
        })?;

    Ok(Html(html).into_response())
}

// ─── Artifact detail ─────────────────────────────────────────────────

async fn artifact_detail(
    State(state): State<AppState>,
    session: Session,
    Path((org, project, slug)): Path<(String, String, String)>,
) -> Result<Response, Response> {
    let orgs = &session.user.orgs;
    require_org_membership(&state, orgs, &org)?;

    if !validate_slug(&project) {
        return Err(error_page(
            &state,
            StatusCode::BAD_REQUEST,
            "Invalid request",
            "Invalid project name.",
        ));
    }

    let artifact = state
        .platform_client
        .get_artifact_by_slug(&session.access_token, &slug)
        .await
        .map_err(|e| match e {
            forage_core::platform::PlatformError::NotFound(_) => error_page(
                &state,
                StatusCode::NOT_FOUND,
                "Not found",
                "This release could not be found.",
            ),
            other => {
                tracing::error!("failed to fetch artifact: {other}");
                error_page(
                    &state,
                    StatusCode::INTERNAL_SERVER_ERROR,
                    "Something went wrong",
                    "Please try again.",
                )
            }
        })?;

    let html = state
        .templates
        .render(
            "pages/artifact_detail.html.jinja",
            context! {
                title => format!("{} - {} - {} - Forage", artifact.context.title, project, org),
                description => artifact.context.description,
                user => context! { username => session.user.username },
                csrf_token => &session.csrf_token,
                current_org => &org,
                orgs => orgs_context(orgs),
                org_name => &org,
                project_name => &project,
                active_tab => "projects",
                artifact => context! {
                    slug => artifact.slug,
                    title => artifact.context.title,
                    description => artifact.context.description,
                    web => artifact.context.web,
                    pr => artifact.context.pr,
                    created_at => artifact.created_at,
                    source_user => artifact.source.as_ref().and_then(|s| s.user.clone()),
                    source_email => artifact.source.as_ref().and_then(|s| s.email.clone()),
                    source_type => artifact.source.as_ref().and_then(|s| s.source_type.clone()),
                    run_url => artifact.source.as_ref().and_then(|s| s.run_url.clone()),
                    commit_sha => artifact.git_ref.as_ref().map(|r| r.commit_sha.clone()),
                    branch => artifact.git_ref.as_ref().and_then(|r| r.branch.clone()),
                    commit_message => artifact.git_ref.as_ref().and_then(|r| r.commit_message.clone()),
                    version => artifact.git_ref.as_ref().and_then(|r| r.version.clone()),
                    repo_url => artifact.git_ref.as_ref().and_then(|r| r.repo_url.clone()),
                    destinations => artifact.destinations.iter().map(|d| {
                        context! { name => d.name, environment => d.environment }
                    }).collect::<Vec<_>>(),
                },
            },
        )
        .map_err(|e| {
            tracing::error!("template error: {e:#}");
            error_page(
                &state,
                StatusCode::INTERNAL_SERVER_ERROR,
                "Something went wrong",
                "Please try again.",
            )
        })?;

    Ok(Html(html).into_response())
}

// ─── Usage ──────────────────────────────────────────────────────────

async fn usage(
    State(state): State<AppState>,
    session: Session,
    Path(org): Path<String>,
) -> Result<Response, Response> {
    let orgs = &session.user.orgs;
    let current_org_data = require_org_membership(&state, orgs, &org)?;

    let projects = state
        .platform_client
        .list_projects(&session.access_token, &org)
        .await
        .unwrap_or_default();

    let html = state
        .templates
        .render(
            "pages/usage.html.jinja",
            context! {
                title => format!("Usage - {org} - Forage"),
                description => format!("Usage and plan for {org}"),
                user => context! { username => session.user.username },
                csrf_token => &session.csrf_token,
                current_org => &org,
                orgs => orgs_context(orgs),
                org_name => &org,
                role => &current_org_data.role,
                project_count => projects.len(),
                active_tab => "usage",
            },
        )
        .map_err(|e| {
            tracing::error!("template error: {e:#}");
            error_page(
                &state,
                StatusCode::INTERNAL_SERVER_ERROR,
                "Something went wrong",
                "Please try again.",
            )
        })?;

    Ok(Html(html).into_response())
}

// ─── Timeline builder (shared between dashboard, project detail, releases) ───

struct ArtifactWithProject {
    artifact: forage_core::platform::Artifact,
    project_name: String,
}

struct TimelineData {
    timeline: Vec<minijinja::Value>,
    lanes: Vec<minijinja::Value>,
}

fn build_timeline(items: Vec<ArtifactWithProject>, org_name: &str) -> TimelineData {
    struct RawRelease {
        value: minijinja::Value,
        has_dests: bool,
    }

    let mut raw_releases: Vec<RawRelease> = Vec::new();
    let mut env_set = std::collections::BTreeSet::new();

    for item in items {
        let artifact = item.artifact;
        let project = &item.project_name;

        let mut release_envs = Vec::new();
        let dests: Vec<minijinja::Value> = artifact
            .destinations
            .iter()
            .map(|d| {
                env_set.insert(d.environment.clone());
                release_envs.push(d.environment.clone());
                context! {
                    name => d.name,
                    environment => d.environment,
                    type_name => d.type_name,
                    type_version => d.type_version,
                }
            })
            .collect();

        let has_dests = !dests.is_empty();
        let dest_envs_str = release_envs.join(",");
        raw_releases.push(RawRelease {
            value: context! {
                slug => artifact.slug,
                title => artifact.context.title,
                description => artifact.context.description,
                project_name => project,
                org_name => org_name,
                created_at => artifact.created_at,
                commit_sha => artifact.git_ref.as_ref().map(|r| r.commit_sha.clone()),
                branch => artifact.git_ref.as_ref().and_then(|r| r.branch.clone()),
                version => artifact.git_ref.as_ref().and_then(|r| r.version.clone()),
                source_user => artifact.source.as_ref().and_then(|s| s.user.clone()),
                source_type => artifact.source.as_ref().and_then(|s| s.source_type.clone()),
                destinations => dests,
                dest_envs => dest_envs_str,
            },
            has_dests,
        });
    }

    let lanes: Vec<minijinja::Value> = env_set
        .into_iter()
        .map(|env| context! { name => env })
        .collect();

    let mut timeline_items: Vec<minijinja::Value> = Vec::new();
    let mut hidden_buf: Vec<minijinja::Value> = Vec::new();

    for raw in raw_releases {
        if raw.has_dests {
            if !hidden_buf.is_empty() {
                let count = hidden_buf.len();
                timeline_items.push(context! {
                    kind => "hidden",
                    count => count,
                    releases => std::mem::take(&mut hidden_buf),
                });
            }
            timeline_items.push(context! {
                kind => "release",
                release => raw.value,
            });
        } else {
            hidden_buf.push(raw.value);
        }
    }
    if !hidden_buf.is_empty() {
        let count = hidden_buf.len();
        timeline_items.push(context! {
            kind => "hidden",
            count => count,
            releases => std::mem::take(&mut hidden_buf),
        });
    }

    TimelineData {
        timeline: timeline_items,
        lanes,
    }
}

/// Fetch all artifacts across projects and return as ArtifactWithProject list.
async fn fetch_org_artifacts(
    state: &AppState,
    access_token: &str,
    org: &str,
    projects: &[String],
) -> Vec<ArtifactWithProject> {
    let mut items = Vec::new();
    for project in projects {
        let artifacts = state
            .platform_client
            .list_artifacts(access_token, org, project)
            .await
            .unwrap_or_default();
        for artifact in artifacts {
            items.push(ArtifactWithProject {
                artifact,
                project_name: project.clone(),
            });
        }
    }
    items
}

// ─── Releases (Up-inspired pipeline) ─────────────────────────────────

async fn releases_page(
    State(state): State<AppState>,
    session: Session,
    Path(org): Path<String>,
) -> Result<Response, Response> {
    let orgs = &session.user.orgs;
    require_org_membership(&state, orgs, &org)?;

    let projects = state
        .platform_client
        .list_projects(&session.access_token, &org)
        .await
        .unwrap_or_default();

    let items = fetch_org_artifacts(&state, &session.access_token, &org, &projects).await;
    let data = build_timeline(items, &org);

    let html = state
        .templates
        .render(
            "pages/releases.html.jinja",
            context! {
                title => format!("Releases - {org} - Forage"),
                description => format!("Deployment pipeline for {org}"),
                user => context! { username => session.user.username },
                csrf_token => &session.csrf_token,
                current_org => &org,
                orgs => orgs_context(orgs),
                org_name => &org,
                timeline => data.timeline,
                lanes => data.lanes,
                active_tab => "releases",
            },
        )
        .map_err(|e| {
            tracing::error!("template error: {e:#}");
            error_page(
                &state,
                StatusCode::INTERNAL_SERVER_ERROR,
                "Something went wrong",
                "Please try again.",
            )
        })?;

    Ok(Html(html).into_response())
}

// ─── Destinations ────────────────────────────────────────────────────

async fn destinations_page(
    State(state): State<AppState>,
    session: Session,
    Path(org): Path<String>,
) -> Result<Response, Response> {
    let orgs = &session.user.orgs;
    let current_org = require_org_membership(&state, orgs, &org)?;
    let is_admin = current_org.role == "owner" || current_org.role == "admin";

    let projects = state
        .platform_client
        .list_projects(&session.access_token, &org)
        .await
        .unwrap_or_default();

    // Aggregate unique destinations from artifacts
    let mut destinations = Vec::new();
    let mut seen = std::collections::HashSet::new();

    for project in &projects {
        let artifacts = state
            .platform_client
            .list_artifacts(&session.access_token, &org, project)
            .await
            .unwrap_or_default();

        for artifact in &artifacts {
            for dest in &artifact.destinations {
                let key = (dest.name.clone(), dest.environment.clone());
                if seen.insert(key) {
                    destinations.push(context! {
                        name => dest.name,
                        environment => dest.environment,
                        project_name => project,
                        artifact_title => artifact.context.title,
                        artifact_slug => artifact.slug,
                        created_at => artifact.created_at,
                    });
                }
            }
        }
    }

    let html = state
        .templates
        .render(
            "pages/destinations.html.jinja",
            context! {
                title => format!("Destinations - {org} - Forage"),
                description => format!("Deployment destinations for {org}"),
                user => context! { username => session.user.username },
                csrf_token => &session.csrf_token,
                current_org => &org,
                orgs => orgs_context(orgs),
                org_name => &org,
                destinations => destinations,
                is_admin => is_admin,
                active_tab => "destinations",
            },
        )
        .map_err(|e| {
            tracing::error!("template error: {e:#}");
            error_page(
                &state,
                StatusCode::INTERNAL_SERVER_ERROR,
                "Something went wrong",
                "Please try again.",
            )
        })?;

    Ok(Html(html).into_response())
}

// ─── Members ────────────────────────────────────────────────────────

async fn members_page(
    State(state): State<AppState>,
    session: Session,
    Path(org): Path<String>,
) -> Result<Response, Response> {
    let orgs = &session.user.orgs;
    let current_org = require_org_membership(&state, orgs, &org)?;

    let members = state
        .platform_client
        .list_members(&session.access_token, &current_org.organisation_id)
        .await
        .unwrap_or_default();

    let is_admin = current_org.role == "owner" || current_org.role == "admin";

    let html = state
        .templates
        .render(
            "pages/members.html.jinja",
            context! {
                title => format!("Members - {org} - Forage"),
                description => format!("Members of {org}"),
                user => context! { username => session.user.username },
                csrf_token => &session.csrf_token,
                current_org => &org,
                orgs => orgs_context(orgs),
                org_name => &org,
                is_admin => is_admin,
                active_tab => "members",
                members => members.iter().map(|m| context! {
                    user_id => m.user_id,
                    username => m.username,
                    role => m.role,
                    joined_at => m.joined_at,
                }).collect::<Vec<_>>(),
            },
        )
        .map_err(|e| {
            tracing::error!("template error: {e:#}");
            error_page(
                &state,
                StatusCode::INTERNAL_SERVER_ERROR,
                "Something went wrong",
                "Please try again.",
            )
        })?;

    Ok(Html(html).into_response())
}

#[derive(Deserialize)]
struct AddMemberForm {
    username: String,
    role: String,
    _csrf: String,
}

async fn add_member_submit(
    State(state): State<AppState>,
    session: Session,
    Path(org): Path<String>,
    Form(form): Form<AddMemberForm>,
) -> Result<Response, Response> {
    let orgs = &session.user.orgs;
    let current_org = require_org_membership(&state, orgs, &org)?;
    require_admin(&state, current_org)?;

    if !auth::validate_csrf(&session, &form._csrf) {
        return Err(error_page(
            &state,
            StatusCode::FORBIDDEN,
            "Invalid request",
            "CSRF validation failed. Please try again.",
        ));
    }

    let _ = state
        .platform_client
        .add_member(
            &session.access_token,
            &current_org.organisation_id,
            &form.username,
            &form.role,
        )
        .await
        .map_err(|e| {
            tracing::error!("failed to add member: {e}");
            error_page(
                &state,
                StatusCode::INTERNAL_SERVER_ERROR,
                "Something went wrong",
                "Please try again.",
            )
        })?;

    Ok(Redirect::to(&format!("/orgs/{org}/settings/members")).into_response())
}

#[derive(Deserialize)]
struct UpdateRoleForm {
    role: String,
    _csrf: String,
}

async fn update_member_role_submit(
    State(state): State<AppState>,
    session: Session,
    Path((org, user_id)): Path<(String, String)>,
    Form(form): Form<UpdateRoleForm>,
) -> Result<Response, Response> {
    let orgs = &session.user.orgs;
    let current_org = require_org_membership(&state, orgs, &org)?;
    require_admin(&state, current_org)?;

    if !auth::validate_csrf(&session, &form._csrf) {
        return Err(error_page(
            &state,
            StatusCode::FORBIDDEN,
            "Invalid request",
            "CSRF validation failed. Please try again.",
        ));
    }

    let _ = state
        .platform_client
        .update_member_role(
            &session.access_token,
            &current_org.organisation_id,
            &user_id,
            &form.role,
        )
        .await
        .map_err(|e| {
            tracing::error!("failed to update member role: {e}");
            error_page(
                &state,
                StatusCode::INTERNAL_SERVER_ERROR,
                "Something went wrong",
                "Please try again.",
            )
        })?;

    Ok(Redirect::to(&format!("/orgs/{org}/settings/members")).into_response())
}

#[derive(Deserialize)]
struct CsrfForm {
    _csrf: String,
}

async fn remove_member_submit(
    State(state): State<AppState>,
    session: Session,
    Path((org, user_id)): Path<(String, String)>,
    Form(form): Form<CsrfForm>,
) -> Result<Response, Response> {
    let orgs = &session.user.orgs;
    let current_org = require_org_membership(&state, orgs, &org)?;
    require_admin(&state, current_org)?;

    if !auth::validate_csrf(&session, &form._csrf) {
        return Err(error_page(
            &state,
            StatusCode::FORBIDDEN,
            "Invalid request",
            "CSRF validation failed. Please try again.",
        ));
    }

    state
        .platform_client
        .remove_member(
            &session.access_token,
            &current_org.organisation_id,
            &user_id,
        )
        .await
        .map_err(|e| {
            tracing::error!("failed to remove member: {e}");
            error_page(
                &state,
                StatusCode::INTERNAL_SERVER_ERROR,
                "Something went wrong",
                "Please try again.",
            )
        })?;

    Ok(Redirect::to(&format!("/orgs/{org}/settings/members")).into_response())
}
