//! Context and schema operation bindings.

use crate::schema::Schema;
use pyo3::prelude::*;

/// Optimize schema for context window (5-level progressive disclosure).
#[pyfunction]
pub fn optimize_context(py: Python<'_>, schema: &Schema) -> PyResult<PyObject> {
    let start = std::time::Instant::now();
    let config = Default::default();
    let result = altimate_core::context::optimize_context(&schema.inner, &config)
        .map_err(|e| pyo3::exceptions::PyRuntimeError::new_err(e))?;
    crate::sdk::timed_emit("optimizeContext", start);
    crate::convert::to_py_result(py, &result)
}

/// Optimize schema for a specific query (prune to relevant tables/columns).
#[pyfunction]
pub fn optimize_for_query(py: Python<'_>, sql: &str, schema: &Schema) -> PyResult<PyObject> {
    let start = std::time::Instant::now();
    let config = Default::default();
    let result = altimate_core::context::optimize_for_query(sql, &schema.inner, &config)
        .map_err(|e| pyo3::exceptions::PyRuntimeError::new_err(e))?;
    crate::sdk::timed_emit("optimizeForQuery", start);
    crate::convert::to_py_result(py, &result)
}

/// Prune schema to only tables/columns referenced by a SQL query.
#[pyfunction]
pub fn prune_schema(py: Python<'_>, sql: &str, schema: &Schema) -> PyResult<PyObject> {
    let start = std::time::Instant::now();
    let result = altimate_core::pruner::prune_schema(sql, &schema.inner)
        .map_err(|e| pyo3::exceptions::PyRuntimeError::new_err(e))?;
    crate::sdk::timed_emit("pruneSchema", start);
    crate::convert::to_py_result(py, &result)
}

/// Diff two schemas with breaking change detection.
#[pyfunction]
pub fn diff_schemas(
    py: Python<'_>,
    old_schema: &Schema,
    new_schema: &Schema,
) -> PyResult<PyObject> {
    let start = std::time::Instant::now();
    let result = altimate_core::schema::diff::diff_schemas(&old_schema.inner, &new_schema.inner);
    crate::sdk::timed_emit("diffSchemas", start);
    crate::convert::to_py_result(py, &result)
}

/// Import DDL into a Schema.
#[pyfunction]
#[pyo3(signature = (ddl, dialect="generic"))]
pub fn import_ddl(ddl: &str, dialect: &str) -> PyResult<Schema> {
    let start = std::time::Instant::now();
    let d = crate::convert::parse_dialect(dialect)?;
    let inner = altimate_core::schema::ddl::parse_ddl(ddl, d)
        .map_err(|e| pyo3::exceptions::PyValueError::new_err(format!("{e}")))?;
    crate::sdk::timed_emit_with_dialect("importDdl", dialect, start);
    Ok(Schema { inner })
}

/// Export schema as CREATE TABLE DDL statements.
#[pyfunction]
pub fn export_ddl(schema: &Schema) -> String {
    let start = std::time::Instant::now();
    let result = altimate_core::schema::ddl::to_ddl(&schema.inner);
    crate::sdk::timed_emit("exportDdl", start);
    result
}

/// Compute a SHA-256 fingerprint of the schema (for caching/change detection).
#[pyfunction]
pub fn schema_fingerprint(schema: &Schema) -> String {
    let start = std::time::Instant::now();
    let result = altimate_core::context::schema_fingerprint(&schema.inner);
    crate::sdk::timed_emit("schemaFingerprint", start);
    result
}

/// Generate INFORMATION_SCHEMA introspection queries for a database.
#[pyfunction]
#[pyo3(signature = (db_type, database, schema_name=None))]
pub fn introspection_sql(
    py: Python<'_>,
    db_type: &str,
    database: &str,
    schema_name: Option<&str>,
) -> PyResult<PyObject> {
    let start = std::time::Instant::now();
    let dt = parse_db_type(db_type)?;
    let result = altimate_core::introspect::generate_introspection_sql(dt, database, schema_name);
    crate::sdk::timed_emit("introspectionSql", start);
    crate::convert::to_py_result(py, &result)
}

fn parse_db_type(s: &str) -> PyResult<altimate_core::introspect::DatabaseType> {
    use altimate_core::introspect::DatabaseType;
    match s.to_lowercase().as_str() {
        "postgres" | "postgresql" => Ok(DatabaseType::Postgres),
        "snowflake" => Ok(DatabaseType::Snowflake),
        "bigquery" => Ok(DatabaseType::BigQuery),
        "mysql" => Ok(DatabaseType::MySQL),
        "redshift" => Ok(DatabaseType::Redshift),
        _ => Err(pyo3::exceptions::PyValueError::new_err(format!(
            "unsupported db type: '{s}'. Supported: postgres, snowflake, bigquery, mysql, redshift"
        ))),
    }
}
