use tsafe_core::tooling_inventory::{
    check_inventory, init_tooling, suggest_keys, SuggestKey, SuggestKeysRequest,
};

#[test]
fn init_tooling_writes_repo_scoped_inventory_files() {
    let tmp = tempfile::tempdir().unwrap();

    let report = init_tooling(tmp.path(), Some("databricks/athn_dev/"), false).unwrap();

    assert!(report.created);
    assert!(report.keys_path.ends_with(".tsafe/tooling/keys.ini"));
    assert!(report.policy_path.ends_with(".tsafe/tooling/policy.toml"));
    assert!(report.readme_path.ends_with(".tsafe/tooling/README.md"));

    let keys_ini = std::fs::read_to_string(&report.keys_path).unwrap();
    assert!(keys_ini.contains("# tsafe secret inventory for"));
    assert!(keys_ini.contains("namespace = databricks/athn_dev/"));
    assert!(keys_ini.contains("[ci-cd-spn]"));
    assert!(keys_ini.contains("key/name = purpose | consumer | rotation"));

    let policy = std::fs::read_to_string(&report.policy_path).unwrap();
    assert!(policy.contains("auto_write_keys_ini = true"));
    assert!(policy.contains("auto_write_vault_values = false"));
}

#[test]
fn suggest_keys_adds_missing_slots_without_secret_values() {
    let tmp = tempfile::tempdir().unwrap();
    init_tooling(tmp.path(), Some("databricks/athn_dev/"), false).unwrap();

    let report = suggest_keys(
        tmp.path(),
        SuggestKeysRequest {
            namespace: "databricks/athn_dev/".to_string(),
            source: "mcp".to_string(),
            reason: "terraform deployment needs CI credentials".to_string(),
            apply: true,
            keys: vec![SuggestKey {
                key: "ci_secret".to_string(),
                purpose: "SPN secret".to_string(),
                consumer: "ADO service connection athn-dev-sc".to_string(),
                rotation: "365d KV policy".to_string(),
                section: Some("ci-cd-spn".to_string()),
            }],
        },
    )
    .unwrap();

    assert_eq!(report.added_keys, vec!["databricks/athn_dev/ci_secret"]);
    assert!(report.receipt_path.is_some());
    assert!(report
        .suggestions_path
        .ends_with(".tsafe/tooling/suggestions.jsonl"));

    let keys_ini = std::fs::read_to_string(tmp.path().join(".tsafe/tooling/keys.ini")).unwrap();
    assert!(keys_ini.contains(
        "databricks/athn_dev/ci_secret = SPN secret | ADO service connection athn-dev-sc | 365d KV policy"
    ));
    assert!(!keys_ini.contains("supersecret"));

    let check = check_inventory(tmp.path()).unwrap();
    assert!(check.ok, "{check:#?}");
    assert_eq!(check.entries.len(), 1);
    assert_eq!(check.entries[0].key, "databricks/athn_dev/ci_secret");
}

#[test]
fn suggest_keys_rejects_invalid_keys_and_injected_metadata_rows() {
    let tmp = tempfile::tempdir().unwrap();
    init_tooling(tmp.path(), Some("databricks/athn_dev/"), false).unwrap();

    let invalid_key = suggest_keys(
        tmp.path(),
        SuggestKeysRequest {
            namespace: "databricks/athn_dev/".to_string(),
            source: "mcp".to_string(),
            reason: "terraform deployment".to_string(),
            apply: true,
            keys: vec![SuggestKey {
                key: "databricks/athn_dev/bad key".to_string(),
                purpose: "SPN secret".to_string(),
                consumer: "ADO service connection".to_string(),
                rotation: "365d KV policy".to_string(),
                section: Some("ci-cd-spn".to_string()),
            }],
        },
    )
    .unwrap_err();
    assert!(
        invalid_key.to_string().contains("suggested key"),
        "{invalid_key}"
    );

    let injected_metadata = suggest_keys(
        tmp.path(),
        SuggestKeysRequest {
            namespace: "databricks/athn_dev/".to_string(),
            source: "mcp".to_string(),
            reason: "terraform deployment".to_string(),
            apply: true,
            keys: vec![SuggestKey {
                key: "ci_secret".to_string(),
                purpose: "SPN secret\n[evil]".to_string(),
                consumer: "ADO service connection".to_string(),
                rotation: "365d KV policy".to_string(),
                section: Some("ci-cd-spn".to_string()),
            }],
        },
    )
    .unwrap_err();
    assert!(
        injected_metadata.to_string().contains("control characters"),
        "{injected_metadata}"
    );

    let injected_reason = suggest_keys(
        tmp.path(),
        SuggestKeysRequest {
            namespace: "databricks/athn_dev/".to_string(),
            source: "mcp".to_string(),
            reason: "safe\n[evil]".to_string(),
            apply: true,
            keys: vec![SuggestKey {
                key: "ci_secret".to_string(),
                purpose: "SPN secret".to_string(),
                consumer: "ADO service connection".to_string(),
                rotation: "365d KV policy".to_string(),
                section: Some("ci-cd-spn".to_string()),
            }],
        },
    )
    .unwrap_err();
    assert!(
        injected_reason.to_string().contains("control characters"),
        "{injected_reason}"
    );
}

#[test]
fn check_inventory_flags_duplicate_and_malformed_rows() {
    let tmp = tempfile::tempdir().unwrap();
    let tooling = tmp.path().join(".tsafe/tooling");
    std::fs::create_dir_all(&tooling).unwrap();
    std::fs::write(
        tooling.join("keys.ini"),
        r#"[inventory]
schema = tsafe.tooling.keys.v1
namespace = databricks/athn_dev/

[ci-cd-spn]
databricks/athn_dev/app_id = App ID | Terraform | static
databricks/athn_dev/app_id = Duplicate | Terraform | static
not-a-namespaced-key = missing separators
"#,
    )
    .unwrap();

    let check = check_inventory(tmp.path()).unwrap();
    assert!(!check.ok);
    assert!(check
        .errors
        .iter()
        .any(|error| error.contains("duplicate key")));
    assert!(check
        .errors
        .iter()
        .any(|error| error.contains("expected `key = purpose | consumer | rotation`")));
}
