#![allow(missing_docs)]

//! Documentation generation for Shuck configuration options.

use std::fmt::Write;

use crate::config::{ConfigFieldMetadata, ConfigSectionMetadata, configuration_metadata};

pub fn generate_settings_reference() -> String {
    let mut output = String::new();
    output.push_str("# Settings Reference\n\n");
    output.push_str("{/* This file is generated by `pnpm generate:config`. */}\n\n");
    output.push_str(
        "This page is generated from Shuck's Rust configuration metadata and lists the supported `shuck.toml` and `.shuck.toml` settings.\n\n",
    );
    output.push_str(
        "Use [Configuration](/docs/configuration) for discovery, precedence, and examples of how config files are resolved.\n\n",
    );

    for section in configuration_metadata() {
        emit_section(&mut output, section, &mut Vec::new());
    }

    output
}

fn emit_section(output: &mut String, section: &ConfigSectionMetadata, parents: &mut Vec<&str>) {
    parents.push(section.key);
    let path = parents.join(".");
    let heading = if parents.len() == 1 { "##" } else { "###" };

    let _ = writeln!(output, "{heading} `[{path}]`\n");
    output.push_str(section.docs);
    output.push_str("\n\n");

    for field in section.fields {
        emit_field(output, field, &path);
    }

    for nested in section.sections {
        emit_section(output, nested, parents);
    }

    parents.pop();
}

fn emit_field(output: &mut String, field: &ConfigFieldMetadata, section_path: &str) {
    let _ = writeln!(output, "#### `{}`\n", field.key);
    output.push_str(field.docs);
    output.push_str("\n\n");
    let _ = writeln!(output, "**Default value**: `{}`\n", field.default);
    let _ = writeln!(output, "**Type**: `{}`\n", field.value_type);
    output.push_str("**Example usage**:\n\n");
    output.push_str("```toml\n");
    let _ = writeln!(output, "[{section_path}]");
    output.push_str(field.example);
    output.push_str("\n```\n\n");
    output.push_str("---\n\n");
}

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

    #[test]
    fn generated_reference_includes_known_sections() {
        let reference = generate_settings_reference();

        assert!(reference.contains("## `[check]`"));
        assert!(reference.contains("## `[lint]`"));
        assert!(reference.contains("### `[lint.rule-options.c001]`"));
        assert!(reference.contains("#### `embedded`"));
        assert!(!reference.contains("## `[format]`"));
    }
}
