//! Helper functions for command implementations

use std::collections::HashMap;
use std::path::PathBuf;
use typedialog_core::form_parser;
use typedialog_core::helpers;
use typedialog_core::prelude::*;

/// Print results with encryption/redaction support
pub fn print_results(
    results: &HashMap<String, serde_json::Value>,
    format: &str,
    output_file: &Option<PathBuf>,
    fields: &[form_parser::FieldDefinition],
    encryption_context: &helpers::EncryptionContext,
    global_config: Option<&typedialog_core::config::EncryptionDefaults>,
) -> Result<()> {
    let output =
        helpers::format_results_secure(results, fields, format, encryption_context, global_config)?;

    if let Some(path) = output_file {
        std::fs::write(path, &output).map_err(Error::io)?;
    } else {
        println!("{}", output);
    }

    Ok(())
}

/// Recursively flatten nested JSON objects into a single-level map
/// Converts {"a": {"b": {"c": "value"}}} to {"a_b_c": "value"}
pub fn flatten_json_object(
    obj: &serde_json::Map<String, serde_json::Value>,
) -> HashMap<String, serde_json::Value> {
    let mut result = HashMap::new();
    flatten_recursive(obj, "", &mut result);
    result
}

fn flatten_recursive(
    obj: &serde_json::Map<String, serde_json::Value>,
    prefix: &str,
    result: &mut HashMap<String, serde_json::Value>,
) {
    for (key, value) in obj.iter() {
        let new_key = if prefix.is_empty() {
            key.clone()
        } else {
            format!("{}_{}", prefix, key)
        };

        match value {
            serde_json::Value::Object(nested) => {
                flatten_recursive(nested, &new_key, result);
            }
            serde_json::Value::Array(arr) => {
                result.insert(new_key, serde_json::Value::Array(arr.clone()));
            }
            _ => {
                result.insert(new_key, value.clone());
            }
        }
    }
}

/// Extract defaults from Nickel export using schema-driven approach
pub fn extract_nickel_defaults(
    obj: &serde_json::Map<String, serde_json::Value>,
    form_fields: &[form_parser::FieldDefinition],
) -> HashMap<String, serde_json::Value> {
    use typedialog_core::nickel::{DefaultsExtractor, FieldMapper, NickelFieldIR, NickelSchemaIR};

    let mut schema_fields = Vec::new();
    for field in form_fields {
        if let Some(nickel_path) = &field.nickel_path {
            schema_fields.push(NickelFieldIR {
                path: nickel_path.clone(),
                flat_name: nickel_path.join("-"),
                alias: field.nickel_alias.clone(),
                nickel_type: typedialog_core::nickel::NickelType::String,
                doc: None,
                default: None,
                optional: false,
                contract: None,
                contract_call: None,
                group: None,
                fragment_marker: None,
                is_array_of_records: false,
                array_element_fields: None,
                encryption_metadata: None,
            });
        }
    }

    if !schema_fields.is_empty() {
        let schema = NickelSchemaIR {
            name: "form".to_string(),
            description: None,
            fields: schema_fields,
        };
        if let Ok(mapper) = FieldMapper::from_schema(&schema) {
            return DefaultsExtractor::extract(&serde_json::Value::Object(obj.clone()), &mapper);
        }
    }

    flatten_json_object(obj)
}
