#!/usr/bin/env nu

# API Routes and handlers for Provisioning System
# Defines all REST API endpoints and their handlers

use ../lib_provisioning/utils/settings.nu *
use ../main_provisioning/query.nu *

# Route definitions for the API server
export def get_route_definitions []: nothing -> list {
    [
        {
            method: "GET"
            path: "/api/v1/health"
            handler: "health_check"
            description: "Health check endpoint"
            parameters: []
        }
        {
            method: "GET"
            path: "/api/v1/query"
            handler: "query_infrastructure"
            description: "Query infrastructure state"
            parameters: [
                { name: "target", type: "string", required: false, default: "servers", description: "Query target (servers, metrics, logs)" }
                { name: "infra", type: "string", required: false, description: "Infrastructure name" }
                { name: "provider", type: "string", required: false, description: "Provider filter" }
                { name: "find", type: "string", required: false, description: "Search filter" }
                { name: "format", type: "string", required: false, default: "json", description: "Output format" }
            ]
        }
        {
            method: "POST"
            path: "/api/v1/query"
            handler: "complex_query"
            description: "Execute complex queries with request body"
            body_schema: {
                type: "object"
                properties: {
                    query_type: { type: "string", enum: ["infrastructure", "metrics", "logs", "ai"] }
                    target: { type: "string" }
                    filters: { type: "object" }
                    ai_query: { type: "string", description: "Natural language query" }
                    aggregations: { type: "array" }
                }
            }
        }
        {
            method: "GET"
            path: "/api/v1/metrics"
            handler: "get_metrics"
            description: "Retrieve system metrics"
            parameters: [
                { name: "timerange", type: "string", default: "1h", description: "Time range (1m, 5m, 1h, 1d)" }
                { name: "metric_type", type: "string", description: "Metric type filter" }
                { name: "aggregation", type: "string", default: "avg", description: "Aggregation method" }
            ]
        }
        {
            method: "GET"
            path: "/api/v1/logs"
            handler: "get_logs"
            description: "Retrieve system logs"
            parameters: [
                { name: "level", type: "string", default: "info", description: "Log level filter" }
                { name: "service", type: "string", description: "Service name filter" }
                { name: "since", type: "string", default: "1h", description: "Time since" }
                { name: "limit", type: "integer", default: 100, description: "Number of entries" }
            ]
        }
        {
            method: "GET"
            path: "/api/v1/dashboard"
            handler: "get_dashboard_data"
            description: "Dashboard data endpoint"
            parameters: [
                { name: "view", type: "string", default: "overview", description: "Dashboard view" }
                { name: "refresh", type: "boolean", default: false, description: "Force refresh" }
            ]
        }
        {
            method: "GET"
            path: "/api/v1/servers"
            handler: "list_servers"
            description: "List all servers"
            parameters: [
                { name: "status", type: "string", description: "Status filter" }
                { name: "provider", type: "string", description: "Provider filter" }
                { name: "infra", type: "string", description: "Infrastructure filter" }
            ]
        }
        {
            method: "GET"
            path: "/api/v1/servers/{id}"
            handler: "get_server"
            description: "Get specific server details"
            path_params: [
                { name: "id", type: "string", required: true, description: "Server ID" }
            ]
        }
        {
            method: "GET"
            path: "/api/v1/servers/{id}/status"
            handler: "get_server_status"
            description: "Get server status and metrics"
            path_params: [
                { name: "id", type: "string", required: true, description: "Server ID" }
            ]
        }
        {
            method: "GET"
            path: "/api/v1/servers/{id}/logs"
            handler: "get_server_logs"
            description: "Get server-specific logs"
            path_params: [
                { name: "id", type: "string", required: true, description: "Server ID" }
            ]
        }
        {
            method: "POST"
            path: "/api/v1/servers"
            handler: "create_server"
            description: "Create new server"
            body_schema: {
                type: "object"
                required: ["name", "provider"]
                properties: {
                    name: { type: "string" }
                    provider: { type: "string" }
                    infra: { type: "string" }
                    instance_type: { type: "string" }
                    count: { type: "integer", default: 1 }
                }
            }
        }
        {
            method: "DELETE"
            path: "/api/v1/servers/{id}"
            handler: "delete_server"
            description: "Delete server"
            path_params: [
                { name: "id", type: "string", required: true, description: "Server ID" }
            ]
        }
        {
            method: "GET"
            path: "/api/v1/ai/query"
            handler: "ai_query"
            description: "Natural language infrastructure queries"
            parameters: [
                { name: "q", type: "string", required: true, description: "Natural language query" }
                { name: "context", type: "string", description: "Context for the query" }
            ]
        }
        {
            method: "POST"
            path: "/api/v1/ai/analyze"
            handler: "ai_analyze"
            description: "AI-powered infrastructure analysis"
            body_schema: {
                type: "object"
                properties: {
                    analysis_type: { type: "string", enum: ["cost", "performance", "security", "optimization"] }
                    timerange: { type: "string", default: "24h" }
                    target: { type: "string" }
                }
            }
        }
        {
            method: "GET"
            path: "/api/v1/dataframes/query"
            handler: "dataframe_query"
            description: "Query infrastructure data using dataframes"
            parameters: [
                { name: "source", type: "string", required: true, description: "Data source (logs, metrics, events)" }
                { name: "query", type: "string", required: true, description: "Polars/SQL-like query" }
                { name: "format", type: "string", default: "json", description: "Output format" }
            ]
        }
        {
            method: "WebSocket"
            path: "/ws/stream"
            handler: "websocket_stream"
            description: "Real-time updates via WebSocket"
            parameters: [
                { name: "subscribe", type: "array", description: "Subscription topics" }
            ]
        }
    ]
}

# Generate OpenAPI/Swagger specification
export def generate_api_spec []: nothing -> record {
    let routes = get_route_definitions

    {
        openapi: "3.0.3"
        info: {
            title: "Provisioning System API"
            description: "REST API for infrastructure provisioning and management"
            version: "1.0.0"
            contact: {
                name: "Provisioning Team"
                url: "https://github.com/provisioning-rs"
            }
        }
        servers: [
            {
                url: "http://localhost:8080"
                description: "Development server"
            }
        ]
        paths: ($routes | generate_paths)
        components: {
            schemas: (generate_schemas)
            securitySchemes: {
                BearerAuth: {
                    type: "http"
                    scheme: "bearer"
                }
            }
        }
        security: [
            { BearerAuth: [] }
        ]
    }
}

def generate_paths []: list -> record {
    let paths = {}

    $in | each { |route|
        let path_key = ($route.path | str replace -a "{id}" "{id}")

        $paths | insert $path_key {
            ($route.method | str downcase): {
                summary: $route.description
                parameters: ($route.parameters? | default [] | each { |param|
                    {
                        name: $param.name
                        in: "query"
                        required: ($param.required? | default false)
                        schema: { type: $param.type }
                        description: $param.description?
                    }
                })
                responses: {
                    "200": {
                        description: "Successful response"
                        content: {
                            "application/json": {
                                schema: { type: "object" }
                            }
                        }
                    }
                    "400": {
                        description: "Bad request"
                    }
                    "500": {
                        description: "Internal server error"
                    }
                }
            }
        }
    } | last
}

def generate_schemas []: nothing -> record {
    {
        Error: {
            type: "object"
            properties: {
                error: { type: "string" }
                message: { type: "string" }
                code: { type: "integer" }
            }
        }
        HealthCheck: {
            type: "object"
            properties: {
                status: { type: "string" }
                service: { type: "string" }
                version: { type: "string" }
                timestamp: { type: "string" }
            }
        }
        Server: {
            type: "object"
            properties: {
                id: { type: "string" }
                name: { type: "string" }
                provider: { type: "string" }
                status: { type: "string" }
                ip_address: { type: "string" }
                created_at: { type: "string" }
            }
        }
        Metrics: {
            type: "object"
            properties: {
                timestamp: { type: "string" }
                cpu_usage: { type: "number" }
                memory_usage: { type: "number" }
                disk_usage: { type: "number" }
                network_io: { type: "object" }
            }
        }
        LogEntry: {
            type: "object"
            properties: {
                timestamp: { type: "string" }
                level: { type: "string" }
                service: { type: "string" }
                message: { type: "string" }
                metadata: { type: "object" }
            }
        }
    }
}

# Generate route documentation
export def generate_route_docs []: nothing -> str {
    let routes = get_route_definitions

    let header = "# Provisioning API Routes\n\nThis document describes all available API endpoints.\n\n"

    let route_docs = ($routes | each { |route|
        let params_doc = if ($route.parameters? | length) > 0 {
            "\n**Parameters:**\n" + ($route.parameters | each { |p|
                $"- `($p.name)` \\(($p.type)\\): ($p.description? | default 'No description')"
            } | str join "\n")
        } else { "" }

        let body_doc = if ($route.body_schema? | is-not-empty) {
            $"\n**Request Body:**\n```json\n($route.body_schema | to json)\n```"
        } else { "" }

        $"## ($route.method) ($route.path)\n\n($route.description)($params_doc)($body_doc)\n"
    } | str join "\n")

    $header + $route_docs
}

# Validate route configuration
export def validate_routes []: nothing -> record {
    let routes = get_route_definitions
    let validation_results = []

    let path_conflicts = ($routes | group-by path | each { |path, group|
        if ($group | length) > 1 {
            let methods = ($group | get method)
            let duplicate_methods = ($methods | uniq | length) != ($methods | length)

            if $duplicate_methods {
                { path: $path, issue: "duplicate_methods", methods: $methods }
            }
        }
    } | compact)

    {
        total_routes: ($routes | length)
        unique_paths: ($routes | get path | uniq | length)
        path_conflicts: $path_conflicts
        validation_passed: ($path_conflicts | length) == 0
    }
}