// src/table_definition/handlers/get_profile_tree.rs
use tonic::{Request, Response, Status};
use sqlx::PgPool;
use common::proto::komp_ac::{
    common::Empty,
    table_definition::{
        ProfileTreeResponse,
        profile_tree_response::{Table, Profile}
    }
};

pub async fn get_profile_tree(
    db_pool: &PgPool,
    _request: Request<Empty>,
) -> Result<Response<ProfileTreeResponse>, Status> {
    let mut profiles = Vec::new();

    // Get all schemas (internally changed from profiles to schemas)
    let schema_records = sqlx::query!(
        "SELECT id, name FROM schemas ORDER BY name"
    )
    .fetch_all(db_pool)
    .await
    .map_err(|e| Status::internal(format!("Failed to fetch schemas: {}", e)))?;

    for schema in schema_records {
        // Get all tables with their dependencies from the links table
        let tables = sqlx::query!(
            r#"
            SELECT
                td.id as table_id,
                td.table_name,
                COALESCE(
                    json_agg(
                        json_build_object(
                            'linked_name', ltd.table_name,
                            'required', tdl.is_required
                        )
                    ) FILTER (WHERE ltd.id IS NOT NULL),
                    '[]'::json
                ) as dependencies
            FROM table_definitions td
            LEFT JOIN table_definition_links tdl ON td.id = tdl.source_table_id
            LEFT JOIN table_definitions ltd ON tdl.linked_table_id = ltd.id
            WHERE td.schema_id = $1
            GROUP BY td.id, td.table_name
            ORDER BY td.table_name
            "#,
            schema.id
        )
        .fetch_all(db_pool)
        .await
        .map_err(|e| Status::internal(format!("Failed to fetch tables: {}", e)))?;

        // Convert to protobuf format
        let proto_tables = tables.into_iter()
            .map(|record| {
                // Handle the Option<Value> properly
                let dependencies = record.dependencies
                    .map(|val| serde_json::from_value::<Vec<serde_json::Value>>(val))
                    .transpose()
                    .unwrap_or_else(|_| Some(Vec::new()))
                    .unwrap_or_default();

                Table {
                    id: record.table_id,
                    name: record.table_name,
                    depends_on: dependencies
                        .into_iter()
                        .filter_map(|d| d["linked_name"].as_str().map(|s| s.to_string()))
                        .collect()
                }
            })
            .collect();

        // External API still returns "profiles" for compatibility
        profiles.push(Profile {
            name: schema.name,
            tables: proto_tables
        });
    }

    Ok(Response::new(ProfileTreeResponse { profiles }))
}
