/*
 * HDGL HTTP API Module - Peer Synchronization
 * Provides REST API for state sync and peer communication
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <time.h>

#define API_PORT 9998
#define MAX_REQUEST_SIZE 8192
#define MAX_RESPONSE_SIZE 16384

// External bridge state (compatibility layer)
#include "bridge_globals.h"

// NetCat integration
#include "hdgl_netcat.h"

// HTTP response builder
static void send_http_response(int client_fd, int status_code, const char* content_type, const char* body) {
    char response[MAX_RESPONSE_SIZE];
    const char* status_text = (status_code == 200) ? "OK" :
                              (status_code == 404) ? "Not Found" :
                              (status_code == 500) ? "Internal Server Error" : "Unknown";

    int body_len = strlen(body);

    snprintf(response, sizeof(response),
        "HTTP/1.1 %d %s\r\n"
        "Content-Type: %s\r\n"
        "Content-Length: %d\r\n"
        "Access-Control-Allow-Origin: *\r\n"
        "Access-Control-Allow-Methods: GET, POST, OPTIONS\r\n"
        "Connection: close\r\n"
        "\r\n"
        "%s",
        status_code, status_text, content_type, body_len, body);

    /* ignore write return intentionally */
    (void)write(client_fd, response, strlen(response));
}

// GET /api/status - Node status and state
static void handle_status(int client_fd) {
    char json[MAX_RESPONSE_SIZE];

    pthread_mutex_lock(&g_bridge_lock);

    // Build JSON response
    snprintf(json, sizeof(json),
        "{\n"
        "  \"node_id\": %d,\n"
        "  \"evolution\": %d,\n"
        "  \"evolution_count\": %d,\n"
        "  \"consensus_count\": %d,\n"
        "  \"state\": [%.12f, %.12f, %.12f, %.12f, %.12f, %.12f, %.12f],\n"
        "  \"phase_variance\": %.6f,\n"
        "  \"frequency_hz\": %.2f,\n"
        "  \"timestamp\": %ld,\n"
        "  \"uptime\": %ld,\n"
        "  \"version\": \"1.0-C\"\n"
        "}",
        g_node_id,
        g_evolution_count,
        g_evolution_count,
        g_consensus_count,
        g_analog_state[0], g_analog_state[1], g_analog_state[2],
        g_analog_state[3], g_analog_state[4], g_analog_state[5], g_analog_state[6],
        g_phase_variance,
        32768.0,
        time(NULL),
        (long)(g_evolution_count / 32768)  // Uptime in seconds
    );

    pthread_mutex_unlock(&g_bridge_lock);

    send_http_response(client_fd, 200, "application/json", json);
}

// GET /api/peers - Connected peers
static void handle_peers(int client_fd) {
    char json[MAX_RESPONSE_SIZE];

    // TODO: Track connected peers
    snprintf(json, sizeof(json),
        "{\n"
        "  \"peers\": [],\n"
        "  \"count\": 0,\n"
        "  \"discovery_method\": \"ipfs\"\n"
        "}");

    send_http_response(client_fd, 200, "application/json", json);
}

// GET /metrics - Prometheus metrics
static void handle_metrics(int client_fd) {
    char metrics[MAX_RESPONSE_SIZE];

    pthread_mutex_lock(&g_bridge_lock);

    snprintf(metrics, sizeof(metrics),
        "# HELP hdgl_evolution_count Total evolution cycles\n"
        "# TYPE hdgl_evolution_count counter\n"
        "hdgl_evolution_count{node=\"%d\"} %d\n"
        "\n"
        "# HELP hdgl_consensus_count Consensus detection count\n"
        "# TYPE hdgl_consensus_count counter\n"
        "hdgl_consensus_count{node=\"%d\"} %d\n"
        "\n"
        "# HELP hdgl_state_dimensions Analog state dimensions\n"
        "# TYPE hdgl_state_dimensions gauge\n"
        "hdgl_state_dimensions{node=\"%d\",dim=\"0\"} %.12f\n"
        "hdgl_state_dimensions{node=\"%d\",dim=\"1\"} %.12f\n"
        "hdgl_state_dimensions{node=\"%d\",dim=\"2\"} %.12f\n"
        "hdgl_state_dimensions{node=\"%d\",dim=\"3\"} %.12f\n"
        "hdgl_state_dimensions{node=\"%d\",dim=\"4\"} %.12f\n"
        "hdgl_state_dimensions{node=\"%d\",dim=\"5\"} %.12f\n"
        "hdgl_state_dimensions{node=\"%d\",dim=\"6\"} %.12f\n",
        g_node_id, g_evolution_count,
        g_node_id, g_consensus_count,
        g_node_id, g_analog_state[0],
        g_node_id, g_analog_state[1],
        g_node_id, g_analog_state[2],
        g_node_id, g_analog_state[3],
        g_node_id, g_analog_state[4],
        g_node_id, g_analog_state[5],
        g_node_id, g_analog_state[6]
    );

    pthread_mutex_unlock(&g_bridge_lock);

    send_http_response(client_fd, 200, "text/plain", metrics);
}

// GET /api/netcat - NetCat status and analog state
static void handle_netcat_status(int client_fd) {
    char json[MAX_RESPONSE_SIZE];
    get_netcat_status(json, sizeof(json));
    send_http_response(client_fd, 200, "application/json", json);
}

// GET /api/graph - ASCII graph of analog state (for CLI display)
static void handle_graph(int client_fd) {
    char response[MAX_RESPONSE_SIZE];

    pthread_mutex_lock(&g_bridge_lock);

    // Build ASCII bar graph
    int len = snprintf(response, sizeof(response),
        "╔════════════════════════════════════════════════════╗\n"
        "║  ANALOG MAINNET - 8D STATE VISUALIZATION         ║\n"
        "╚════════════════════════════════════════════════════╝\n\n"
        "Evolution: %d  |  Consensus: %d  |  Phase Var: %.3f\n\n"
        "8D Real Components:\n",
        g_evolution_count, g_consensus_count, g_phase_variance
    );

    // Find max for scaling
    double max_val = 1.0;
    for (int i = 0; i < 7; i++) {
        if (fabs(g_analog_state[i]) > max_val) {
            max_val = fabs(g_analog_state[i]);
        }
    }

    // Draw bars
    for (int i = 0; i < 7; i++) {
        int bar_width = (int)((fabs(g_analog_state[i]) / max_val) * 30);
        if (bar_width > 30) bar_width = 30;

        len += snprintf(response + len, sizeof(response) - len, "D%d [", i + 1);
        for (int j = 0; j < 30; j++) {
            len += snprintf(response + len, sizeof(response) - len,
                           j < bar_width ? "█" : "░");
        }
        len += snprintf(response + len, sizeof(response) - len,
                       "] %.2e\n", g_analog_state[i]);
    }

    len += snprintf(response + len, sizeof(response) - len,
        "\nFrequency: 32,768 Hz\n"
        "Node ID: %d\n",
        g_node_id
    );

    pthread_mutex_unlock(&g_bridge_lock);

    send_http_response(client_fd, 200, "text/plain; charset=utf-8", response);
}

// Parse HTTP request and route
static void handle_request(int client_fd) {
    char buffer[MAX_REQUEST_SIZE];
    int bytes_read = read(client_fd, buffer, sizeof(buffer) - 1);

    if (bytes_read <= 0) {
        close(client_fd);
        return;
    }

    buffer[bytes_read] = '\0';

    // Parse first line (method and path)
    char method[16], path[256];
    sscanf(buffer, "%s %s", method, path);

    // Route handling
    if (strcmp(method, "GET") == 0) {
        if (strcmp(path, "/api/status") == 0) {
            handle_status(client_fd);
        } else if (strcmp(path, "/api/graph") == 0) {
            handle_graph(client_fd);
        } else if (strcmp(path, "/api/peers") == 0) {
            handle_peers(client_fd);
        } else if (strcmp(path, "/metrics") == 0) {
            handle_metrics(client_fd);
        } else if (strcmp(path, "/api/netcat") == 0) {
            handle_netcat_status(client_fd);
        } else if (strcmp(path, "/") == 0) {
            send_http_response(client_fd, 200, "text/plain",
                "HDGL Analog Bridge v1.0 - C Implementation\n"
                "Endpoints:\n"
                "  GET /api/status - Node status (JSON)\n"
                "  GET /api/graph - ASCII visualization\n"
                "  GET /api/peers - Connected peers\n"
                "  GET /api/netcat - NetCat analog status\n"
                "  GET /metrics - Prometheus metrics\n");
        } else {
            send_http_response(client_fd, 404, "text/plain", "Not Found");
        }
    } else if (strcmp(method, "OPTIONS") == 0) {
        // CORS preflight
        send_http_response(client_fd, 200, "text/plain", "");
    } else {
        send_http_response(client_fd, 404, "text/plain", "Not Found");
    }

    close(client_fd);
}

// HTTP server thread
void* http_server_thread(void* arg) {
    int port = *((int*)arg);
    int server_fd, client_fd;
    struct sockaddr_in server_addr, client_addr;
    socklen_t client_len = sizeof(client_addr);

    printf("DEBUG: http_server_thread() started, port=%d\n", port);
    fflush(stdout);

    // Create socket
    server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd < 0) {
        perror("ERROR: socket creation failed");
        fflush(stderr);
        return NULL;
    }
    printf("DEBUG: Socket created (fd=%d)\n", server_fd);
    fflush(stdout);

    // Set socket options
    int opt = 1;
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
        perror("ERROR: setsockopt failed");
        fflush(stderr);
    }

    // Bind
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(port);

    printf("DEBUG: Attempting to bind to port %d...\n", port);
    fflush(stdout);

    if (bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        perror("ERROR: bind failed");
        fprintf(stderr, "ERROR: Could not bind to port %d\n", port);
        fflush(stderr);
        close(server_fd);
        return NULL;
    }
    printf("DEBUG: Bind successful on port %d\n", port);
    fflush(stdout);

    // Listen
    if (listen(server_fd, 10) < 0) {
        perror("ERROR: listen failed");
        fflush(stderr);
        close(server_fd);
        return NULL;
    }

    printf("✓ HTTP API listening on port %d\n", port);
    fflush(stdout);

    // Accept loop
    while (1) {
        client_fd = accept(server_fd, (struct sockaddr*)&client_addr, &client_len);
        if (client_fd < 0) {
            if (errno == EINTR) continue;
            perror("accept");
            break;
        }

        // Handle request (could spawn thread for concurrency)
        handle_request(client_fd);
    }

    close(server_fd);
    return NULL;
}

// Start HTTP API server
int start_http_api(int port) {
    static int api_port;
    api_port = port;

    printf("DEBUG: start_http_api() called with port %d\n", port);
    fflush(stdout);

    pthread_t thread;
    int ret = pthread_create(&thread, NULL, http_server_thread, &api_port);
    if (ret != 0) {
        fprintf(stderr, "ERROR: pthread_create failed: %s (code %d)\n", strerror(ret), ret);
        fflush(stderr);
        return -1;
    }

    printf("DEBUG: HTTP API thread created successfully\n");
    fflush(stdout);

    pthread_detach(thread);
    printf("DEBUG: HTTP API thread detached\n");
    fflush(stdout);
    return 0;
}
