//! Embedded constitution and template assets.
//!
//! This module provides compile-time embedded access to Decapod's methodology documents.
//! All constitution files (core, specs, plugins) are baked into the binary for
//! hermetic deployment - no external files required.
//!
//! # For AI Agents
//!
//! - **Constitution is embedded in binary**: No need for external doc files
//! - **Use `decapod docs show <path>`**: Access docs via CLI, not direct file reads
//! - **Override mechanism**: Projects can override docs in `.decapod/constitution/`
//! - **Merge semantics**: Overrides append to embedded base (see `get_merged_doc`)
//! - **Templates for scaffolding**: CLAUDE.md, GEMINI.md, etc. are embedded here

use std::path::Path;

/// Macro to embed constitution documents at compile time as text.
///
/// Generates:
/// - Public constants for each embedded document
/// - `get_embedded_doc(path)` function for lookup
/// - `list_docs()` function for discovery
macro_rules! embedded_docs {
    ($($path:expr => $const_name:ident),* $(,)?) => {
        $(
            pub const $const_name: &str =
                include_str!(concat!("../../constitution/embedded/", $path));
        )*

        pub fn get_embedded_doc(path: &str) -> Option<String> {
            let key = path.strip_prefix("embedded/").unwrap_or(path);
            match key {
                $( $path => Some($const_name.to_string()), )*
                _ => None,
            }
        }

        pub fn list_docs() -> Vec<String> {
            vec![ $( format!("embedded/{}", $path), )* ]
        }
    };
}

embedded_docs! {
    "core/CLAIMS.md" => EMBEDDED_CORE_CLAIMS,
    "core/CONTROL_PLANE.md" => EMBEDDED_CORE_CONTROL_PLANE,
    "core/DECAPOD.md" => EMBEDDED_CORE_DECAPOD,
    "core/DEMANDS.md" => EMBEDDED_CORE_DEMANDS,
    "core/DEPRECATION.md" => EMBEDDED_CORE_DEPRECATION,
    "core/DOC_RULES.md" => EMBEDDED_CORE_DOC_RULES,
    "core/GLOSSARY.md" => EMBEDDED_CORE_GLOSSARY,
    "core/KNOWLEDGE.md" => EMBEDDED_CORE_KNOWLEDGE,
    "core/MEMORY.md" => EMBEDDED_CORE_MEMORY,
    "core/PLUGINS.md" => EMBEDDED_CORE_PLUGINS,
    "core/SOUL.md" => EMBEDDED_CORE_SOUL,
    "core/STORE_MODEL.md" => EMBEDDED_CORE_STORE_MODEL,
    "specs/AMENDMENTS.md" => EMBEDDED_SPECS_AMENDMENTS,
    "specs/ARCHITECTURE.md" => EMBEDDED_SPECS_ARCHITECTURE,
    "specs/INTENT.md" => EMBEDDED_SPECS_INTENT,
    "specs/SYSTEM.md" => EMBEDDED_SPECS_SYSTEM,
    "plugins/ARCHIVE.md" => EMBEDDED_PLUGINS_ARCHIVE,
    "plugins/CONTEXT.md" => EMBEDDED_PLUGINS_CONTEXT,
    "plugins/CRON.md" => EMBEDDED_PLUGINS_CRON,
    "plugins/DB_BROKER.md" => EMBEDDED_PLUGINS_DB_BROKER,
    "plugins/EMERGENCY_PROTOCOL.md" => EMBEDDED_PLUGINS_EMERGENCY_PROTOCOL,
    "plugins/FEEDBACK.md" => EMBEDDED_PLUGINS_FEEDBACK,
    "plugins/HEALTH.md" => EMBEDDED_PLUGINS_HEALTH,
    "plugins/HEARTBEAT.md" => EMBEDDED_PLUGINS_HEARTBEAT,
    "plugins/KNOWLEDGE.md" => EMBEDDED_PLUGINS_KNOWLEDGE,
    "plugins/MANIFEST.md" => EMBEDDED_PLUGINS_MANIFEST,
    "plugins/POLICY.md" => EMBEDDED_PLUGINS_POLICY,
    "plugins/REFLEX.md" => EMBEDDED_PLUGINS_REFLEX,
    "plugins/TODO.md" => EMBEDDED_PLUGINS_TODO,
    "plugins/TODO_USER.md" => EMBEDDED_PLUGINS_TODO_USER,
    "plugins/TRUST.md" => EMBEDDED_PLUGINS_TRUST,
    "plugins/WATCHER.md" => EMBEDDED_PLUGINS_WATCHER,
}

/// Legacy function - now just forwards to get_embedded_doc
pub fn get_doc(path: &str) -> Option<String> {
    get_embedded_doc(path)
}

/// Get only the override document from .decapod/OVERRIDE.md for a specific component
pub fn get_override_doc(repo_root: &Path, relative_path: &str) -> Option<String> {
    let override_path = repo_root.join(".decapod").join("OVERRIDE.md");

    if !override_path.exists() {
        return None;
    }

    let override_content = std::fs::read_to_string(&override_path).ok()?;
    extract_component_override(&override_content, relative_path)
}

/// Extract a specific component's override content from OVERRIDE.md
fn extract_component_override(override_content: &str, component_path: &str) -> Option<String> {
    // Only look after the "CHANGES ARE NOT PERMITTED ABOVE THIS LINE" marker
    let override_start = override_content.find("CHANGES ARE NOT PERMITTED ABOVE THIS LINE")?;
    let searchable_content = &override_content[override_start..];

    // Look for the section heading: ### core/DECAPOD.md (or other path)
    let section_marker = format!("\n### {}", component_path);

    let start = searchable_content.find(&section_marker)?;
    let content_start = start + section_marker.len();

    // Find the next ### heading or end of file
    let content_after = &searchable_content[content_start..];
    let end = content_after
        .find("\n### ")
        .map(|pos| content_start + pos)
        .unwrap_or(searchable_content.len());

    let extracted = searchable_content[content_start..end].trim();

    if extracted.is_empty() {
        None
    } else {
        Some(extracted.to_string())
    }
}

/// Get merged document (embedded base + optional project override from OVERRIDE.md)
pub fn get_merged_doc(repo_root: &Path, relative_path: &str) -> Option<String> {
    // Get embedded base
    let embedded_content = get_embedded_doc(relative_path)?;

    // Check for component-specific override in .decapod/OVERRIDE.md
    if let Some(override_content) = get_override_doc(repo_root, relative_path) {
        return Some(merge_override_content(&embedded_content, &override_content));
    }

    Some(embedded_content)
}

/// Merge embedded content with override additions
fn merge_override_content(embedded_content: &str, override_content: &str) -> String {
    format!(
        "{}\n\n---\n\n## Project Overrides\n\n{}",
        embedded_content.trim(),
        override_content.trim()
    )
}

// Root templates (AGENTS.md, CLAUDE.md, GEMINI.md) - embedded for scaffolding
pub const TEMPLATE_AGENTS: &str = include_str!("../../templates/AGENTS.md");
pub const TEMPLATE_CLAUDE: &str = include_str!("../../templates/CLAUDE.md");
pub const TEMPLATE_GEMINI: &str = include_str!("../../templates/GEMINI.md");
pub const TEMPLATE_README: &str = include_str!("../../templates/README.md");
pub const TEMPLATE_OVERRIDE: &str = include_str!("../../templates/OVERRIDE.md");

pub fn get_template(name: &str) -> Option<String> {
    match name {
        "AGENTS.md" => Some(TEMPLATE_AGENTS.to_string()),
        "CLAUDE.md" => Some(TEMPLATE_CLAUDE.to_string()),
        "GEMINI.md" => Some(TEMPLATE_GEMINI.to_string()),
        "README.md" => Some(TEMPLATE_README.to_string()),
        "OVERRIDE.md" => Some(TEMPLATE_OVERRIDE.to_string()),
        _ => None,
    }
}
