use utoipa::OpenApi;
use common_contracts::messages::*;
use common_contracts::observability::*;
use common_contracts::config_models::*;
use common_contracts::registry::{ProviderMetadata, ConfigFieldSchema, FieldType, ConfigKey};
use common_contracts::dtos::{WorkflowHistoryDto, WorkflowHistorySummaryDto};
use crate::api;

#[derive(OpenApi)]
#[openapi(
    paths(
        api::health_check,
        api::start_workflow,
        api::get_task_progress,
        api::resolve_symbol,
        api::get_llm_providers_config,
        api::update_llm_providers_config,
        // api::get_analysis_template_sets,
        // api::update_analysis_template_sets,
        api::get_templates,
        api::get_template_by_id,
        api::update_template,
        api::delete_template,
        api::get_data_sources_config,
        api::update_data_sources_config,
        api::test_data_source_config,
        api::test_llm_config,
        api::discover_models,
        api::discover_models_preview,
        api::get_registered_providers, // New endpoint
        api::get_workflow_histories,
        api::get_workflow_history_by_id,
    ),
    components(
        schemas(
            // Workflow
            StartWorkflowCommand,
            WorkflowEvent,
            WorkflowDag,
            TaskNode,
            TaskDependency,
            TaskType,
            TaskStatus,
            // Observability
            TaskProgress,
            ServiceStatus,
            HealthStatus,
            ObservabilityTaskStatus,
            // Configs
            LlmProvidersConfig,
            LlmProvider,
            LlmModel,
            AnalysisTemplateSets,
            AnalysisTemplateSet,
            AnalysisModuleConfig,
            DataSourcesConfig,
            DataSourceConfig,
            DataSourceProvider,
            // Registry / Dynamic Config
            ProviderMetadata,
            ConfigFieldSchema,
            FieldType,
            ConfigKey,
            // Request/Response
            api::DataRequest,
            api::RequestAcceptedResponse,
            api::SymbolResolveRequest,
            api::SymbolResolveResponse,
            api::TestConfigRequest,
            api::TestConnectionResponse,
            api::TestLlmConfigRequest,
            // DTOs
            WorkflowHistoryDto,
            WorkflowHistorySummaryDto,
        )
    ),
    tags(
        (name = "workflow", description = "Workflow management endpoints"),
        (name = "config", description = "Configuration management endpoints"),
        (name = "tools", description = "Utility tools"),
        (name = "observability", description = "System observability"),
    )
)]
pub struct ApiDoc;

#[cfg(test)]
mod tests {
    use super::*;
    use std::io::Write;
    use std::path::PathBuf;

    #[test]
    fn generate_openapi_json() {
        let doc = ApiDoc::openapi();
        let json = doc.to_pretty_json().expect("Failed to serialize OpenAPI");
        
        // Locate the workspace root relative to this test file
        // services/api-gateway/src/openapi.rs -> ../../../openapi.json
        let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
        path.push("../../openapi.json");
        
        let mut file = std::fs::File::create(&path).expect("Failed to create openapi.json");
        file.write_all(json.as_bytes()).expect("Failed to write openapi.json");
        println!("OpenAPI Spec written to: {:?}", path);
    }
}
