use forge::signal::compactor;

const MAX_JSON_LINES: usize = 80;

/// Compress jq output. Large JSON responses are truncated with a hint.
pub fn compress_jq(raw: &str) -> String {
    let cleaned = compactor::normalise(raw);
    let lines: Vec<&str> = cleaned.lines().collect();
    if lines.len() <= MAX_JSON_LINES {
        return cleaned;
    }
    let omitted = lines.len() - MAX_JSON_LINES;
    format!(
        "{}\n... [{} more lines — pipe through `jq -c` or add a filter to narrow output] ...",
        lines[..MAX_JSON_LINES].join("\n"),
        omitted
    )
}

/// Strip null/empty fields from JSON output to save tokens.
/// Removes lines like `"key": null`, `"key": ""`, `"key": []`, `"key": {}`.
pub fn compress_json_compact(raw: &str) -> String {
    let cleaned = compactor::normalise(raw);
    let kept: Vec<&str> = cleaned
        .lines()
        .filter(|l| {
            let t = l.trim();
            // Keep non-null/non-empty values
            !t.ends_with(": null,")
                && !t.ends_with(": null")
                && !t.ends_with(": \"\",")
                && !t.ends_with(": \"\"")
                && !t.ends_with(": [],")
                && !t.ends_with(": []")
                && !t.ends_with(": {},")
                && !t.ends_with(": {}")
        })
        .collect();
    let result = kept.join("\n");
    // Still truncate if large
    compress_jq(&result)
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn jq_passthrough_small() {
        let raw = "{\n  \"foo\": 1\n}\n";
        let out = compress_jq(raw);
        assert!(out.contains("foo"), "{out}");
        assert!(!out.contains("more lines"), "{out}");
    }

    #[test]
    fn jq_truncates_large_output() {
        let raw = (0..100)
            .map(|i| format!("  \"key{i}\": \"value{i}\""))
            .collect::<Vec<_>>()
            .join("\n");
        let out = compress_jq(&raw);
        assert!(out.contains("more lines"), "{out}");
    }

    #[test]
    fn json_compact_strips_nulls() {
        let raw = "{\n  \"id\": 1,\n  \"name\": null,\n  \"tags\": [],\n  \"meta\": {}\n}\n";
        let out = compress_json_compact(raw);
        assert!(!out.contains("null"), "{out}");
        assert!(!out.contains("\"tags\": []"), "{out}");
        assert!(out.contains("\"id\": 1"), "{out}");
    }
}
