use crate::process::SchemaTop;
use log::info;
use serde_json::json;
use std::collections::HashMap;
use std::fs;
use std::path::Path;
pub fn generate(generated_dir: &Path, handwritten_dir: &Path) -> anyhow::Result<()> {
let schema_source = generated_dir.join("patched_schemas");
if !schema_source.exists() {
anyhow::bail!("Patched schema directory not found: {}\nRun process step first.", schema_source.display());
}
let rules_dir = generated_dir.join("cel-rules");
fs::create_dir_all(&rules_dir)?;
info!("CEL codegen: schemas={} rules={}", schema_source.display(), rules_dir.display());
let mut raw_schemas: HashMap<String, serde_json::Value> = HashMap::new();
for entry in fs::read_dir(&schema_source)? {
let path = entry?.path();
if path.extension().and_then(|e| e.to_str()) != Some("json") {
continue;
}
let content = fs::read_to_string(&path)?;
let json: serde_json::Value =
serde_json::from_str(&content).map_err(|e| anyhow::anyhow!("failed to parse {}: {}", path.display(), e))?;
let Some(type_name) = json.get("typeName").and_then(|v| v.as_str()) else {
anyhow::bail!("patched schema {} has no 'typeName'", path.display());
};
raw_schemas.insert(type_name.to_string(), json);
}
anyhow::ensure!(!raw_schemas.is_empty(), "no patched schemas found in {}", schema_source.display());
info!("Loaded {} patched schemas", raw_schemas.len());
let mut schemas: HashMap<String, SchemaTop> = HashMap::new();
for (type_name, json) in &raw_schemas {
let schema: SchemaTop = serde_json::from_value(json.clone())
.map_err(|error| anyhow::anyhow!("failed to deserialize patched schema '{}': {}", type_name, error))?;
anyhow::ensure!(
schema.type_name.as_deref() == Some(type_name),
"patched schema '{}' did not preserve its required typeName",
type_name
);
schemas.insert(type_name.clone(), schema);
}
info!("Parsed {} schemas for CEL codegen", schemas.len());
let ds_data = generated_dir.join("data");
let all_rules = generate_data_driven_rules(&ds_data, handwritten_dir);
let rules_json = json!({ "rules": all_rules });
fs::write(rules_dir.join("generated_rules.json"), serde_json::to_string_pretty(&rules_json)?)?;
info!("Generated {} CEL rules total", all_rules.len());
Ok(())
}
fn generate_data_driven_rules(_generated_dir: &Path, _handwritten_dir: &Path) -> Vec<serde_json::Value> {
let rules = Vec::new();
info!("Generated {} data-driven best practice rules", rules.len());
rules
}