//! Content Management API Endpoints
//!
//! Provides comprehensive REST API endpoints for content management operations,
//! including CRUD operations, manual rebuilding, and status checks.

use std::{collections::HashMap, sync::Arc};

use anyhow::Result;
use axum::{
    extract::{Path, Query, State},
    http::StatusCode,
    response::Json,
    routing::{delete, get, post, put},
    Router,
};
use serde::{Deserialize, Serialize};
use tracing::{debug, info};

#[cfg(feature = "content-watcher")]
use super::watcher::ContentWatcher;

/// API response for content operations
#[derive(Debug, Serialize, Deserialize)]
pub struct ContentApiResponse {
    pub success: bool,
    pub message: String,
    pub timestamp: String,
    pub details: Option<serde_json::Value>,
}

/// Content status information
#[derive(Debug, Serialize, Deserialize)]
pub struct ContentStatus {
    pub content_watcher_enabled: bool,
    pub last_rebuild: Option<String>,
    pub pending_changes: u32,
    pub cache_entries: u32,
}

/// Enhanced API response wrapper for consistent error handling
#[derive(Debug, Serialize)]
pub struct ApiResponse<T> {
    pub success: bool,
    pub data: Option<T>,
    pub message: String,
    pub errors: Vec<String>,
}

impl<T> ApiResponse<T> {
    pub fn success(data: T) -> Self {
        Self {
            success: true,
            data: Some(data),
            message: "Success".to_string(),
            errors: Vec::new(),
        }
    }

    pub fn error(message: String) -> Self {
        Self {
            success: false,
            data: None,
            message,
            errors: Vec::new(),
        }
    }

    pub fn validation_error(errors: Vec<String>) -> Self {
        Self {
            success: false,
            data: None,
            message: "Validation failed".to_string(),
            errors,
        }
    }
}

/// Content creation request
#[derive(Debug, Deserialize)]
pub struct CreateContentRequest {
    pub slug: String,
    pub title: String,
    pub content: String,
    pub content_type: String,
    pub language: String,
    pub published: Option<bool>,
    pub draft: Option<bool>,
    pub featured: Option<bool>,
    pub tags: Vec<String>,
    pub category: Option<String>,
    pub excerpt: Option<String>,
    pub description: Option<String>,
    pub author: Option<String>,
}

/// Content update request
#[derive(Debug, Serialize, Deserialize)]
pub struct UpdateContentRequest {
    pub title: Option<String>,
    pub content: Option<String>,
    pub published: Option<bool>,
    pub draft: Option<bool>,
    pub featured: Option<bool>,
    pub tags: Option<Vec<String>>,
    pub category: Option<String>,
    pub excerpt: Option<String>,
    pub description: Option<String>,
    pub author: Option<String>,
}

/// Content query parameters
#[derive(Debug, Deserialize)]
pub struct ContentQuery {
    pub page: Option<usize>,
    pub limit: Option<usize>,
    pub content_type: Option<String>,
    pub language: Option<String>,
    pub state: Option<String>,
    pub category: Option<String>,
    pub tag: Option<String>,
    pub featured: Option<bool>,
}

/// Content list response
#[derive(Debug, Serialize)]
pub struct ContentListResponse {
    pub items: Vec<ContentSummary>,
    pub total: usize,
    pub page: usize,
    pub limit: usize,
    pub has_next: bool,
    pub has_previous: bool,
}

/// Content summary for list responses
#[derive(Debug, Serialize)]
pub struct ContentSummary {
    pub id: String,
    pub slug: String,
    pub title: String,
    pub content_type: String,
    pub language: String,
    pub state: String,
    pub published_at: Option<String>,
    pub updated_at: String,
    pub author: Option<String>,
    pub category: Option<String>,
    pub tags: Vec<String>,
    pub featured: bool,
    pub word_count: Option<usize>,
}

/// Version control request types

/// Create version request
#[derive(Debug, Deserialize)]
pub struct CreateVersionRequest {
    pub author: Option<String>,
    pub version_notes: Option<String>,
}

/// Rollback version request
#[derive(Debug, Deserialize)]
pub struct RollbackVersionRequest {
    pub author: Option<String>,
}

/// Application state for content API
pub struct ContentApiState {
    #[cfg(feature = "content-watcher")]
    pub watcher: Option<Arc<ContentWatcher>>,
    pub content_service: Option<Arc<super::ContentService>>,
}

impl ContentApiState {
    pub fn new() -> Self {
        Self {
            #[cfg(feature = "content-watcher")]
            watcher: None,
            content_service: None,
        }
    }

    #[cfg(feature = "content-watcher")]
    pub fn with_watcher(watcher: Arc<ContentWatcher>) -> Self {
        Self {
            watcher: Some(watcher),
            content_service: None,
        }
    }

    pub fn with_content_service(content_service: Arc<super::ContentService>) -> Self {
        Self {
            #[cfg(feature = "content-watcher")]
            watcher: None,
            content_service: Some(content_service),
        }
    }

    #[cfg(feature = "content-watcher")]
    pub fn with_watcher_and_service(
        watcher: Arc<ContentWatcher>,
        content_service: Arc<super::ContentService>,
    ) -> Self {
        Self {
            watcher: Some(watcher),
            content_service: Some(content_service),
        }
    }
}

/// Create content management API routes
pub fn create_content_api_routes() -> Router<Arc<ContentApiState>> {
    Router::new()
        // Management endpoints
        .route("/rebuild", post(rebuild_content))
        .route("/status", get(get_content_status))
        .route("/cache/clear", post(clear_content_cache))
        .route("/meta/{content_type}/{language}", get(get_meta_config))
        // CRUD endpoints
        .route("/items", post(create_content))
        .route("/items", get(list_content))
        .route("/items/{id}", get(get_content))
        .route("/items/{id}", put(update_content))
        .route("/items/{id}", delete(delete_content))
        .route("/items/{id}/publish", post(publish_content))
        .route("/items/{id}/unpublish", post(unpublish_content))
        .route("/search", get(search_content))
        // Version control endpoints
        .route("/items/{content_path}/versions", get(get_version_history))
        .route("/items/{content_path}/versions", post(create_version))
        .route("/items/{content_path}/versions/{version}", get(get_version))
        .route(
            "/items/{content_path}/versions/{from_version}/diff/{to_version}",
            get(get_version_diff),
        )
        .route(
            "/items/{content_path}/rollback/{target_version}",
            post(rollback_to_version),
        )
}

/// POST /api/content/rebuild - Manually trigger content rebuild
#[cfg_attr(not(feature = "content-watcher"), allow(unused_variables))]
async fn rebuild_content(
    State(state): State<Arc<ContentApiState>>,
) -> Result<Json<ContentApiResponse>, StatusCode> {
    #[cfg(feature = "content-watcher")]
    {
        if let Some(watcher) = &state.watcher {
            match watcher.trigger_rebuild().await {
                Ok(_) => {
                    tracing::info!("Content rebuild triggered successfully via API");

                    // Clear Leptos filter cache if leptos-hydration is active.
                    #[cfg(feature = "leptos-hydration")]
                    rustelo_components_leptos::filter::clear_filter_cache();

                    Ok(Json(ContentApiResponse {
                        success: true,
                        message: "Content rebuild completed successfully".to_string(),
                        timestamp: chrono::Utc::now().to_rfc3339(),
                        details: Some(serde_json::json!({
                            "cache_cleared": true,
                            "watcher_enabled": true
                        })),
                    }))
                }
                Err(e) => {
                    tracing::error!("Content rebuild failed via API: {}", e);
                    Ok(Json(ContentApiResponse {
                        success: false,
                        message: format!("Content rebuild failed: {}", e),
                        timestamp: chrono::Utc::now().to_rfc3339(),
                        details: Some(serde_json::json!({
                            "error": e.to_string()
                        })),
                    }))
                }
            }
        } else {
            Ok(Json(ContentApiResponse {
                success: false,
                message: "Content watcher not available".to_string(),
                timestamp: chrono::Utc::now().to_rfc3339(),
                details: Some(serde_json::json!({
                    "watcher_enabled": false,
                    "reason": "content-watcher feature not enabled or not initialized"
                })),
            }))
        }
    }

    #[cfg(not(feature = "content-watcher"))]
    {
        Ok(Json(ContentApiResponse {
            success: false,
            message: "Content watcher feature not enabled".to_string(),
            timestamp: chrono::Utc::now().to_rfc3339(),
            details: Some(serde_json::json!({
                "watcher_enabled": false,
                "feature_enabled": false
            })),
        }))
    }
}

/// GET /api/content/status - Get content system status
#[cfg_attr(not(feature = "content-watcher"), allow(unused_variables))]
async fn get_content_status(
    State(state): State<Arc<ContentApiState>>,
) -> Result<Json<ContentStatus>, StatusCode> {
    #[cfg(feature = "content-watcher")]
    let watcher_enabled = state.watcher.is_some();

    #[cfg(not(feature = "content-watcher"))]
    let watcher_enabled = false;

    // TODO: Implement actual cache entry counting
    let cache_entries = 0;
    let pending_changes = 0;
    let last_rebuild = Some(chrono::Utc::now().to_rfc3339());

    Ok(Json(ContentStatus {
        content_watcher_enabled: watcher_enabled,
        last_rebuild,
        pending_changes,
        cache_entries,
    }))
}

/// POST /api/content/cache/clear - Clear all content caches
async fn clear_content_cache(
    State(_state): State<Arc<ContentApiState>>,
) -> Result<Json<ContentApiResponse>, StatusCode> {
    #[cfg(feature = "leptos-hydration")]
    rustelo_components_leptos::filter::clear_filter_cache();

    tracing::info!("Content cache cleared via API");

    Ok(Json(ContentApiResponse {
        success: true,
        message: "Content cache cleared successfully".to_string(),
        timestamp: chrono::Utc::now().to_rfc3339(),
        details: Some(serde_json::json!({
            "cache_types_cleared": ["filter_cache"],
            "cache_entries_before": "unknown" // TODO: Track this
        })),
    }))
}

/// GET /api/content/meta/:content_type/:language - Get meta configuration
/// (categories/tags with emojis)
async fn get_meta_config(
    Path((content_type, language)): Path<(String, String)>,
    State(_state): State<Arc<ContentApiState>>,
) -> Result<Json<rustelo_core_lib::categories::MetaConfig>, StatusCode> {
    match rustelo_core_lib::categories::load_meta_config(&content_type, &language) {
        Ok(config) => Ok(Json(config)),
        Err(e) => {
            tracing::error!(
                "Failed to load meta config for {}/{}: {}",
                content_type,
                language,
                e
            );
            Err(StatusCode::NOT_FOUND)
        }
    }
}

/// Create new content
async fn create_content(
    State(state): State<Arc<ContentApiState>>,
    Json(request): Json<CreateContentRequest>,
) -> Result<Json<ApiResponse<serde_json::Value>>, StatusCode> {
    debug!(
        "Creating content: {}/{}",
        request.content_type, request.slug
    );

    let Some(_service) = &state.content_service else {
        return Ok(Json(ApiResponse::error(
            "Content service not available".to_string(),
        )));
    };

    // Validate request
    let validation_errors = validate_create_request(&request);
    if !validation_errors.is_empty() {
        return Ok(Json(ApiResponse::validation_error(validation_errors)));
    }

    // Create markdown content with frontmatter
    let _markdown_content = create_markdown_content(&request);

    // For now, we'll simulate content creation since the actual implementation
    // would require file system operations that are complex in the current
    // architecture
    info!(
        "Content creation simulated: {}/{}",
        request.content_type, request.slug
    );

    let response_data = serde_json::json!({
        "slug": request.slug,
        "title": request.title,
        "content_type": request.content_type,
        "language": request.language,
        "status": "created",
        "message": "Content created successfully (simulated)"
    });

    Ok(Json(ApiResponse::success(response_data)))
}

/// List content with filtering and pagination
async fn list_content(
    State(state): State<Arc<ContentApiState>>,
    Query(query): Query<ContentQuery>,
) -> Result<Json<ApiResponse<ContentListResponse>>, StatusCode> {
    let page = query.page.unwrap_or(1);
    let limit = query.limit.unwrap_or(20).min(100); // Max 100 items per page

    debug!("Listing content: page={}, limit={}", page, limit);

    let Some(_service) = &state.content_service else {
        return Ok(Json(ApiResponse::error(
            "Content service not available".to_string(),
        )));
    };

    // For now, return mock data since full implementation requires integration
    // with the existing file-based content system
    let mock_response = ContentListResponse {
        items: vec![], // Would be populated with actual content
        total: 0,
        page,
        limit,
        has_next: false,
        has_previous: page > 1,
    };

    Ok(Json(ApiResponse::success(mock_response)))
}

/// Get specific content by ID
async fn get_content(
    State(state): State<Arc<ContentApiState>>,
    Path(id): Path<String>,
) -> Result<Json<ApiResponse<serde_json::Value>>, StatusCode> {
    debug!("Getting content: {}", id);

    let Some(_service) = &state.content_service else {
        return Ok(Json(ApiResponse::error(
            "Content service not available".to_string(),
        )));
    };

    // For now, return mock data
    let response_data = serde_json::json!({
        "id": id,
        "message": "Content retrieval not yet fully implemented",
        "status": "mock"
    });

    Ok(Json(ApiResponse::success(response_data)))
}

/// Update existing content
async fn update_content(
    State(state): State<Arc<ContentApiState>>,
    Path(id): Path<String>,
    Json(request): Json<UpdateContentRequest>,
) -> Result<Json<ApiResponse<serde_json::Value>>, StatusCode> {
    debug!("Updating content: {}", id);

    let Some(_service) = &state.content_service else {
        return Ok(Json(ApiResponse::error(
            "Content service not available".to_string(),
        )));
    };

    info!("Content update simulated: {}", id);

    let response_data = serde_json::json!({
        "id": id,
        "status": "updated",
        "message": "Content updated successfully (simulated)",
        "changes": request
    });

    Ok(Json(ApiResponse::success(response_data)))
}

/// Delete content
async fn delete_content(
    State(state): State<Arc<ContentApiState>>,
    Path(id): Path<String>,
) -> Result<Json<ApiResponse<serde_json::Value>>, StatusCode> {
    debug!("Deleting content: {}", id);

    let Some(_service) = &state.content_service else {
        return Ok(Json(ApiResponse::error(
            "Content service not available".to_string(),
        )));
    };

    info!("Content deletion simulated: {}", id);

    let response_data = serde_json::json!({
        "id": id,
        "status": "deleted",
        "message": "Content deleted successfully (simulated)"
    });

    Ok(Json(ApiResponse::success(response_data)))
}

/// Publish content
async fn publish_content(
    State(state): State<Arc<ContentApiState>>,
    Path(id): Path<String>,
) -> Result<Json<ApiResponse<serde_json::Value>>, StatusCode> {
    debug!("Publishing content: {}", id);

    let Some(_service) = &state.content_service else {
        return Ok(Json(ApiResponse::error(
            "Content service not available".to_string(),
        )));
    };

    info!("Content publishing simulated: {}", id);

    let response_data = serde_json::json!({
        "id": id,
        "status": "published",
        "message": "Content published successfully (simulated)"
    });

    Ok(Json(ApiResponse::success(response_data)))
}

/// Unpublish content
async fn unpublish_content(
    State(state): State<Arc<ContentApiState>>,
    Path(id): Path<String>,
) -> Result<Json<ApiResponse<serde_json::Value>>, StatusCode> {
    debug!("Unpublishing content: {}", id);

    let Some(_service) = &state.content_service else {
        return Ok(Json(ApiResponse::error(
            "Content service not available".to_string(),
        )));
    };

    info!("Content unpublishing simulated: {}", id);

    let response_data = serde_json::json!({
        "id": id,
        "status": "unpublished",
        "message": "Content unpublished successfully (simulated)"
    });

    Ok(Json(ApiResponse::success(response_data)))
}

/// Search content
async fn search_content(
    State(state): State<Arc<ContentApiState>>,
    Query(mut query): Query<HashMap<String, String>>,
) -> Result<Json<ApiResponse<ContentListResponse>>, StatusCode> {
    let search_query = query.remove("q").unwrap_or_default();
    let page = query.get("page").and_then(|p| p.parse().ok()).unwrap_or(1);
    let limit = query
        .get("limit")
        .and_then(|l| l.parse().ok())
        .unwrap_or(20)
        .min(100);

    debug!(
        "Searching content: query='{}', page={}, limit={}",
        search_query, page, limit
    );

    let Some(_service) = &state.content_service else {
        return Ok(Json(ApiResponse::error(
            "Content service not available".to_string(),
        )));
    };

    // For now, return mock search results
    let mock_response = ContentListResponse {
        items: vec![], // Would be populated with search results
        total: 0,
        page,
        limit,
        has_next: false,
        has_previous: page > 1,
    };

    Ok(Json(ApiResponse::success(mock_response)))
}

/// Validate content creation request
fn validate_create_request(request: &CreateContentRequest) -> Vec<String> {
    let mut errors = Vec::new();

    if request.slug.is_empty() {
        errors.push("Slug cannot be empty".to_string());
    }

    if request.title.is_empty() {
        errors.push("Title cannot be empty".to_string());
    }

    if request.content.is_empty() {
        errors.push("Content cannot be empty".to_string());
    }

    if request.content_type.is_empty() {
        errors.push("Content type cannot be empty".to_string());
    }

    if request.language.is_empty() {
        errors.push("Language cannot be empty".to_string());
    }

    // Validate slug format (alphanumeric, hyphens, underscores only)
    if !request
        .slug
        .chars()
        .all(|c| c.is_alphanumeric() || c == '-' || c == '_')
    {
        errors.push(
            "Slug can only contain alphanumeric characters, hyphens, and underscores".to_string(),
        );
    }

    errors
}

/// Create markdown content with frontmatter from request
fn create_markdown_content(request: &CreateContentRequest) -> String {
    let mut frontmatter = Vec::new();

    frontmatter.push(format!("title: \"{}\"", request.title.replace('"', "\\\"")));
    frontmatter.push(format!("slug: \"{}\"", request.slug));

    if let Some(published) = request.published {
        frontmatter.push(format!("published: {}", published));
    }

    if let Some(draft) = request.draft {
        frontmatter.push(format!("draft: {}", draft));
    }

    if let Some(featured) = request.featured {
        frontmatter.push(format!("featured: {}", featured));
    }

    if !request.tags.is_empty() {
        frontmatter.push(format!(
            "tags: [{}]",
            request
                .tags
                .iter()
                .map(|t| format!("\"{}\"", t.replace('"', "\\\"")))
                .collect::<Vec<_>>()
                .join(", ")
        ));
    }

    if let Some(ref category) = request.category {
        frontmatter.push(format!("category: \"{}\"", category.replace('"', "\\\"")));
    }

    if let Some(ref excerpt) = request.excerpt {
        frontmatter.push(format!("excerpt: \"{}\"", excerpt.replace('"', "\\\"")));
    }

    if let Some(ref description) = request.description {
        frontmatter.push(format!(
            "description: \"{}\"",
            description.replace('"', "\\\"")
        ));
    }

    if let Some(ref author) = request.author {
        frontmatter.push(format!("author: \"{}\"", author.replace('"', "\\\"")));
    }

    format!(
        "---\n{}\n---\n\n{}",
        frontmatter.join("\n"),
        request.content
    )
}

// ===== VERSION CONTROL ENDPOINTS =====

/// GET /api/content/{content_path}/versions - Get version history
#[cfg(feature = "content-static")]
async fn get_version_history(
    State(state): State<Arc<ContentApiState>>,
    Path(content_path): Path<String>,
) -> Result<Json<ApiResponse<super::version_control::VersionHistory>>, StatusCode> {
    match state.content_service.as_ref() {
        Some(service) => match service.get_content_version_history(&content_path).await {
            Ok(Some(history)) => Ok(Json(ApiResponse::success(history))),
            Ok(None) => Ok(Json(ApiResponse::error(
                "Version control not enabled".to_string(),
            ))),
            Err(e) => {
                tracing::error!("Failed to get version history for {}: {}", content_path, e);
                Ok(Json(ApiResponse::error(format!(
                    "Failed to get version history: {}",
                    e
                ))))
            }
        },
        None => Ok(Json(ApiResponse::error(
            "Content service not available".to_string(),
        ))),
    }
}

/// POST /api/content/{content_path}/versions - Create new version
#[cfg(feature = "content-static")]
async fn create_version(
    State(state): State<Arc<ContentApiState>>,
    Path(content_path): Path<String>,
    Json(request): Json<CreateVersionRequest>,
) -> Result<Json<ApiResponse<String>>, StatusCode> {
    match state.content_service.as_ref() {
        Some(service) => match service
            .create_content_version(&content_path, request.author, request.version_notes)
            .await
        {
            Ok(Some(version)) => Ok(Json(ApiResponse::success(version))),
            Ok(None) => Ok(Json(ApiResponse::error(
                "Version control not enabled or content not found".to_string(),
            ))),
            Err(e) => {
                tracing::error!("Failed to create version for {}: {}", content_path, e);
                Ok(Json(ApiResponse::error(format!(
                    "Failed to create version: {}",
                    e
                ))))
            }
        },
        None => Ok(Json(ApiResponse::error(
            "Content service not available".to_string(),
        ))),
    }
}

/// GET /api/content/{content_path}/versions/{version} - Get specific version
#[cfg(feature = "content-static")]
async fn get_version(
    State(state): State<Arc<ContentApiState>>,
    Path((content_path, version)): Path<(String, String)>,
) -> Result<Json<ApiResponse<rustelo_core_lib::fluent::PageContent>>, StatusCode> {
    match state.content_service.as_ref() {
        Some(service) => match service.get_content_version(&content_path, &version).await {
            Ok(Some(content)) => Ok(Json(ApiResponse::success(content))),
            Ok(None) => Ok(Json(ApiResponse::error("Version not found".to_string()))),
            Err(e) => {
                tracing::error!(
                    "Failed to get version {} for {}: {}",
                    version,
                    content_path,
                    e
                );
                Ok(Json(ApiResponse::error(format!(
                    "Failed to get version: {}",
                    e
                ))))
            }
        },
        None => Ok(Json(ApiResponse::error(
            "Content service not available".to_string(),
        ))),
    }
}

/// GET /api/content/{content_path}/versions/{from_version}/diff/{to_version} -
/// Get version diff
#[cfg(feature = "content-static")]
async fn get_version_diff(
    State(state): State<Arc<ContentApiState>>,
    Path((content_path, from_version, to_version)): Path<(String, String, String)>,
) -> Result<Json<ApiResponse<super::version_control::VersionDiff>>, StatusCode> {
    match state.content_service.as_ref() {
        Some(service) => match service
            .generate_version_diff(&content_path, &from_version, &to_version)
            .await
        {
            Ok(Some(diff)) => Ok(Json(ApiResponse::success(diff))),
            Ok(None) => Ok(Json(ApiResponse::error(
                "Version control not enabled".to_string(),
            ))),
            Err(e) => {
                tracing::error!(
                    "Failed to generate diff from {} to {} for {}: {}",
                    from_version,
                    to_version,
                    content_path,
                    e
                );
                Ok(Json(ApiResponse::error(format!(
                    "Failed to generate diff: {}",
                    e
                ))))
            }
        },
        None => Ok(Json(ApiResponse::error(
            "Content service not available".to_string(),
        ))),
    }
}

/// POST /api/content/{content_path}/rollback/{target_version} - Rollback to
/// version
#[cfg(feature = "content-static")]
async fn rollback_to_version(
    State(state): State<Arc<ContentApiState>>,
    Path((content_path, target_version)): Path<(String, String)>,
    Json(request): Json<RollbackVersionRequest>,
) -> Result<Json<ApiResponse<String>>, StatusCode> {
    match state.content_service.as_ref() {
        Some(service) => match service
            .rollback_content_to_version(&content_path, &target_version, request.author)
            .await
        {
            Ok(Some(new_version)) => {
                tracing::info!(
                    "Successfully rolled back {} to version {} (new version: {})",
                    content_path,
                    target_version,
                    new_version
                );
                Ok(Json(ApiResponse::success(new_version)))
            }
            Ok(None) => Ok(Json(ApiResponse::error(
                "Version control not enabled or target version not found".to_string(),
            ))),
            Err(e) => {
                tracing::error!(
                    "Failed to rollback {} to version {}: {}",
                    content_path,
                    target_version,
                    e
                );
                Ok(Json(ApiResponse::error(format!(
                    "Failed to rollback: {}",
                    e
                ))))
            }
        },
        None => Ok(Json(ApiResponse::error(
            "Content service not available".to_string(),
        ))),
    }
}

// Stub handlers for when content-static is not enabled
#[cfg(not(feature = "content-static"))]
async fn get_version_history(
    Path(_content_path): Path<String>,
) -> Result<Json<ApiResponse<()>>, StatusCode> {
    Ok(Json(ApiResponse::error(
        "Version control requires content-static feature".to_string(),
    )))
}

#[cfg(not(feature = "content-static"))]
async fn create_version(
    Path(_content_path): Path<String>,
    Json(_request): Json<CreateVersionRequest>,
) -> Result<Json<ApiResponse<()>>, StatusCode> {
    Ok(Json(ApiResponse::error(
        "Version control requires content-static feature".to_string(),
    )))
}

#[cfg(not(feature = "content-static"))]
async fn get_version(
    Path((_content_path, _version)): Path<(String, String)>,
) -> Result<Json<ApiResponse<()>>, StatusCode> {
    Ok(Json(ApiResponse::error(
        "Version control requires content-static feature".to_string(),
    )))
}

#[cfg(not(feature = "content-static"))]
async fn get_version_diff(
    Path((_content_path, _from_version, _to_version)): Path<(String, String, String)>,
) -> Result<Json<ApiResponse<()>>, StatusCode> {
    Ok(Json(ApiResponse::error(
        "Version control requires content-static feature".to_string(),
    )))
}

#[cfg(not(feature = "content-static"))]
async fn rollback_to_version(
    Path((_content_path, _target_version)): Path<(String, String)>,
    Json(_request): Json<RollbackVersionRequest>,
) -> Result<Json<ApiResponse<()>>, StatusCode> {
    Ok(Json(ApiResponse::error(
        "Version control requires content-static feature".to_string(),
    )))
}

#[cfg(test)]
mod tests {
    use axum::{
        body::Body,
        http::{Request, StatusCode},
    };
    use tower::ServiceExt;

    use super::*;

    #[tokio::test]
    async fn test_content_status_endpoint() {
        let state = Arc::new(ContentApiState::new());
        let app = create_content_api_routes().with_state(state);

        let response = app
            .oneshot(
                Request::builder()
                    .uri("/api/content/status")
                    .body(Body::empty())
                    .unwrap(),
            )
            .await
            .unwrap();

        assert_eq!(response.status(), StatusCode::OK);
    }

    #[tokio::test]
    async fn test_clear_cache_endpoint() {
        let state = Arc::new(ContentApiState::new());
        let app = create_content_api_routes().with_state(state);

        let response = app
            .oneshot(
                Request::builder()
                    .method("POST")
                    .uri("/api/content/cache/clear")
                    .body(Body::empty())
                    .unwrap(),
            )
            .await
            .unwrap();

        assert_eq!(response.status(), StatusCode::OK);
    }
}
