use phono_backends::{
    client::WorkspaceClient,
    pg_class::{PgClass, PgRelKind},
};
use phono_models::{client::AppDbClient, portal::Portal};
use uuid::Uuid;

pub const PHONO_TABLE_NAMESPACE: &str = "phono";

#[derive(Clone, Debug)]
pub(crate) struct RelationPortalSet {
    pub(crate) rel: PgClass,
    pub(crate) portals: Vec<Portal>,
}

/// Fetch a [`Vec`] of [`RelationPortalSet`]s containing all relations the given
/// user has access to, within the given workspace.
///
/// WARNING: This assumes that `workspace_client` is authenticated with
/// [`RoleAssignment::User`] for the current user.
pub(crate) async fn fetch_all_accessible_portals(
    workspace_id: Uuid,
    app_db: &mut AppDbClient,
    workspace_client: &mut WorkspaceClient,
) -> Result<Vec<RelationPortalSet>, sqlx::Error> {
    let rels = PgClass::with_kind_in([PgRelKind::OrdinaryTable])
        .fetch_all(workspace_client)
        .await?;
    let mut portal_sets: Vec<RelationPortalSet> = Vec::with_capacity(rels.len());
    for rel in rels {
        if rel.regnamespace.as_str() != "pg_catalog"
            && rel.regnamespace.as_str() != "information_schema"
        {
            let mut portals = Portal::belonging_to_workspace(workspace_id)
                .belonging_to_rel(rel.oid)
                .fetch_all(app_db)
                .await?;
            portals.sort_by_key(|value| value.name.clone());
            portal_sets.push(RelationPortalSet { rel, portals });
        }
    }
    portal_sets.sort_by_key(|value| value.rel.relname.clone());

    Ok(portal_sets)
}
