#ifndef GINXSOM_H
#define GINXSOM_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <stdint.h>
#include <stdbool.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>

#include <fcgi_stdio.h>
#include <sqlite3.h>
#include <openssl/sha.h>
#include <openssl/evp.h>
#include <openssl/ec.h>
#include <openssl/obj_mac.h>

/* Constants */
#define GINXSOM_VERSION "0.1.0"
#define MAX_PATH_LEN 4096
#define MAX_CONFIG_LINE 1024
#define SHA256_HEX_LEN 64
#define SHA256_DIGEST_LEN 32
#define MAX_PUBKEY_HEX_LEN 64
#define MAX_MIME_TYPE_LEN 128
#define MAX_FILENAME_LEN 256
#define MAX_CONTENT_LEN 1024
#define DEFAULT_MAX_FILE_SIZE (100 * 1024 * 1024)  // 100MB
#define DEFAULT_MAX_BLOBS_PER_USER 1000
#define DEFAULT_RATE_LIMIT 10

/* Global configuration variables */
extern char g_db_path[MAX_PATH_LEN];
extern char g_storage_dir[MAX_PATH_LEN];

/* Error codes */
typedef enum {
    GINXSOM_OK = 0,
    GINXSOM_ERROR = -1,
    GINXSOM_ERROR_CONFIG = -2,
    GINXSOM_ERROR_DB = -3,
    GINXSOM_ERROR_AUTH = -4,
    GINXSOM_ERROR_STORAGE = -5,
    GINXSOM_ERROR_MEMORY = -6,
    GINXSOM_ERROR_INVALID_REQUEST = -7,
    GINXSOM_ERROR_FILE_TOO_LARGE = -8,
    GINXSOM_ERROR_RATE_LIMIT = -9,
    GINXSOM_ERROR_NOT_FOUND = -10
} ginxsom_error_t;

/* Configuration structure */
typedef struct {
    char socket_path[MAX_PATH_LEN];
    size_t max_file_size;
    char storage_path[MAX_PATH_LEN];
    char database_path[MAX_PATH_LEN];
    
    bool require_auth_upload;
    bool require_auth_get;
    bool require_auth_list;
    
    int max_blobs_per_user;
    int rate_limit_uploads;
} ginxsom_config_t;

/* Blob descriptor structure */
typedef struct {
    char sha256[SHA256_HEX_LEN + 1];
    char pubkey[MAX_PUBKEY_HEX_LEN + 1];
    size_t size;
    char mime_type[MAX_MIME_TYPE_LEN];
    time_t uploaded;
    char filename[MAX_FILENAME_LEN];
} ginxsom_blob_t;

/* Nostr event structure */
typedef struct {
    char id[SHA256_HEX_LEN + 1];
    char pubkey[MAX_PUBKEY_HEX_LEN + 1];
    int kind;
    char content[MAX_CONTENT_LEN];
    time_t created_at;
    time_t expiration;
    char verb[16];  // t tag value: get, upload, list, delete
    char x_hashes[10][SHA256_HEX_LEN + 1];  // x tag values (up to 10)
    int x_count;
    char server[MAX_PATH_LEN];  // server tag value
    char signature[128];
} nostr_event_t;

/* FastCGI context structure */
typedef struct {
    ginxsom_config_t config;
    sqlite3 *db;
    char *request_method;
    char *request_uri;
    char *content_type;
    char *content_length_str;
    size_t content_length;
    char *authorization;
} ginxsom_context_t;

/* Function declarations */

/* config.c */
int ginxsom_load_config(const char *config_path, ginxsom_config_t *config);
void ginxsom_config_init_defaults(ginxsom_config_t *config);

/* database.c */
int ginxsom_db_init(sqlite3 **db, const char *db_path);
int ginxsom_db_close(sqlite3 *db);
int ginxsom_db_store_blob(sqlite3 *db, const ginxsom_blob_t *blob);
int ginxsom_db_delete_blob(sqlite3 *db, const char *sha256, const char *pubkey);
int ginxsom_db_list_blobs(sqlite3 *db, const char *pubkey, ginxsom_blob_t **blobs, int *count);
int ginxsom_db_blob_exists(sqlite3 *db, const char *sha256);
int ginxsom_db_get_user_blob_count(sqlite3 *db, const char *pubkey);

/* auth.c */
int ginxsom_parse_auth_header(const char *auth_header, nostr_event_t *event);
int ginxsom_verify_nostr_event(const nostr_event_t *event);
int ginxsom_validate_auth_for_upload(const nostr_event_t *event, const char *sha256);
int ginxsom_validate_auth_for_delete(const nostr_event_t *event, const char *sha256);
int ginxsom_validate_auth_for_list(const nostr_event_t *event);

/* storage.c */
int ginxsom_store_blob(const char *storage_path, const char *sha256, 
                       const char *data, size_t size, const char *mime_type);
int ginxsom_delete_blob(const char *storage_path, const char *sha256);
char *ginxsom_detect_mime_type(const char *data, size_t size);
int ginxsom_calculate_sha256(const char *data, size_t size, char *sha256_hex);

/* server.c */
int ginxsom_handle_upload(ginxsom_context_t *ctx);
int ginxsom_handle_upload_head(ginxsom_context_t *ctx);
int ginxsom_handle_list(ginxsom_context_t *ctx, const char *pubkey);
int ginxsom_handle_delete(ginxsom_context_t *ctx, const char *sha256);
void ginxsom_send_response(int status, const char *content_type, 
                          const char *body, size_t body_len);
void ginxsom_send_error(int status, const char *reason);

/* utils.c */
char *ginxsom_read_request_body(size_t content_length);
int ginxsom_hex_to_bytes(const char *hex, unsigned char *bytes, size_t bytes_len);
void ginxsom_bytes_to_hex(const unsigned char *bytes, size_t bytes_len, char *hex);
int ginxsom_parse_query_params(const char *query_string, char *params[][2], int max_params);
char *ginxsom_url_decode(const char *encoded);
int ginxsom_create_directory(const char *path);

#endif /* GINXSOM_H */
