/*
 * Test program for key generation
 * Standalone version that doesn't require FastCGI
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sqlite3.h>
#include "../nostr_core_lib/nostr_core/nostr_common.h"
#include "../nostr_core_lib/nostr_core/utils.h"

// Forward declarations
int generate_random_private_key_bytes(unsigned char *key_bytes, size_t len);
int generate_server_keypair(const char *db_path);
int store_blossom_private_key(const char *db_path, const char *seckey);

// Generate random private key bytes using /dev/urandom
int generate_random_private_key_bytes(unsigned char *key_bytes, size_t len) {
  FILE *fp = fopen("/dev/urandom", "rb");
  if (!fp) {
    fprintf(stderr, "ERROR: Cannot open /dev/urandom for key generation\n");
    return -1;
  }

  size_t bytes_read = fread(key_bytes, 1, len, fp);
  fclose(fp);

  if (bytes_read != len) {
    fprintf(stderr, "ERROR: Failed to read %zu bytes from /dev/urandom\n", len);
    return -1;
  }

  return 0;
}

// Store blossom private key in dedicated table
int store_blossom_private_key(const char *db_path, const char *seckey) {
  sqlite3 *db;
  sqlite3_stmt *stmt;
  int rc;

  // Validate key format
  if (!seckey || strlen(seckey) != 64) {
    fprintf(stderr, "ERROR: Invalid blossom private key format\n");
    return -1;
  }

  // Create blossom_seckey table if it doesn't exist
  rc = sqlite3_open_v2(db_path, &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
  if (rc) {
    fprintf(stderr, "ERROR: Can't open database: %s\n", sqlite3_errmsg(db));
    return -1;
  }

  // Create table
  const char *create_sql = "CREATE TABLE IF NOT EXISTS blossom_seckey (id INTEGER PRIMARY KEY CHECK (id = 1), seckey TEXT NOT NULL, created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')), CHECK (length(seckey) = 64))";
  rc = sqlite3_exec(db, create_sql, NULL, NULL, NULL);
  if (rc != SQLITE_OK) {
    fprintf(stderr, "ERROR: Failed to create blossom_seckey table: %s\n", sqlite3_errmsg(db));
    sqlite3_close(db);
    return -1;
  }

  // Store key
  const char *sql = "INSERT OR REPLACE INTO blossom_seckey (id, seckey) VALUES (1, ?)";
  rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
  if (rc != SQLITE_OK) {
    fprintf(stderr, "ERROR: SQL prepare failed: %s\n", sqlite3_errmsg(db));
    sqlite3_close(db);
    return -1;
  }

  sqlite3_bind_text(stmt, 1, seckey, -1, SQLITE_STATIC);
  rc = sqlite3_step(stmt);
  sqlite3_finalize(stmt);
  sqlite3_close(db);

  if (rc != SQLITE_DONE) {
    fprintf(stderr, "ERROR: Failed to store blossom private key\n");
    return -1;
  }

  return 0;
}

// Generate server keypair and store in database
int generate_server_keypair(const char *db_path) {
  printf("Generating server keypair...\n");
  unsigned char seckey_bytes[32];
  char seckey_hex[65];
  char pubkey_hex[65];

  // Generate random private key
  printf("Generating random private key...\n");
  if (generate_random_private_key_bytes(seckey_bytes, 32) != 0) {
    fprintf(stderr, "Failed to generate random bytes\n");
    return -1;
  }

  // Validate the private key
  if (nostr_ec_private_key_verify(seckey_bytes) != NOSTR_SUCCESS) {
    fprintf(stderr, "ERROR: Generated invalid private key\n");
    return -1;
  }

  // Convert to hex
  nostr_bytes_to_hex(seckey_bytes, 32, seckey_hex);

  // Derive public key
  unsigned char pubkey_bytes[32];
  if (nostr_ec_public_key_from_private_key(seckey_bytes, pubkey_bytes) != NOSTR_SUCCESS) {
    fprintf(stderr, "ERROR: Failed to derive public key\n");
    return -1;
  }

  // Convert public key to hex
  nostr_bytes_to_hex(pubkey_bytes, 32, pubkey_hex);

  // Store private key securely
  if (store_blossom_private_key(db_path, seckey_hex) != 0) {
    fprintf(stderr, "ERROR: Failed to store blossom private key\n");
    return -1;
  }

  // Store public key in config
  sqlite3 *db;
  sqlite3_stmt *stmt;
  int rc;

  rc = sqlite3_open_v2(db_path, &db, SQLITE_OPEN_READWRITE, NULL);
  if (rc) {
    fprintf(stderr, "ERROR: Can't open database for config: %s\n", sqlite3_errmsg(db));
    return -1;
  }

  const char *sql = "INSERT OR REPLACE INTO config (key, value, description) VALUES (?, ?, ?)";
  rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
  if (rc != SQLITE_OK) {
    fprintf(stderr, "ERROR: SQL prepare failed: %s\n", sqlite3_errmsg(db));
    sqlite3_close(db);
    return -1;
  }

  sqlite3_bind_text(stmt, 1, "blossom_pubkey", -1, SQLITE_STATIC);
  sqlite3_bind_text(stmt, 2, pubkey_hex, -1, SQLITE_STATIC);
  sqlite3_bind_text(stmt, 3, "Blossom server's public key for Nostr communication", -1, SQLITE_STATIC);

  rc = sqlite3_step(stmt);
  sqlite3_finalize(stmt);
  sqlite3_close(db);

  if (rc != SQLITE_DONE) {
    fprintf(stderr, "ERROR: Failed to store blossom public key in config\n");
    return -1;
  }

  // Display keys for admin setup
  printf("========================================\n");
  printf("SERVER KEYPAIR GENERATED SUCCESSFULLY\n");
  printf("========================================\n");
  printf("Blossom Public Key:  %s\n", pubkey_hex);
  printf("Blossom Private Key: %s\n", seckey_hex);
  printf("========================================\n");
  printf("IMPORTANT: Save the private key securely!\n");
  printf("This key is used for decrypting admin messages.\n");
  printf("========================================\n");

  return 0;
}

int main(int argc, char *argv[]) {
  const char *db_path = "db/ginxsom.db";
  
  if (argc > 1) {
    db_path = argv[1];
  }
  
  printf("Test Key Generation\n");
  printf("===================\n");
  printf("Database: %s\n\n", db_path);
  
  // Initialize nostr crypto
  printf("Initializing nostr crypto system...\n");
  if (nostr_crypto_init() != NOSTR_SUCCESS) {
    fprintf(stderr, "FATAL: Failed to initialize nostr crypto\n");
    return 1;
  }
  printf("Crypto system initialized\n\n");
  
  // Generate keypair
  if (generate_server_keypair(db_path) != 0) {
    fprintf(stderr, "FATAL: Key generation failed\n");
    return 1;
  }
  
  printf("\nKey generation test completed successfully!\n");
  return 0;
}