/*
 * sign_event_client.c — connect to a running n_signer over its abstract
 * UNIX socket and call sign_event, using the shared nsigner client from
 * nostr_core_lib (nostr_core/nsigner_client.h + nostr_core/nsigner_transport.h).
 *
 * Usage: ./sign_event_client [socket_name]
 *
 * Output: the raw JSON-RPC response string, e.g.
 *         {"id":"1","result":"{...signed event...}"}
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "nostr_common.h"
#include "nsigner_transport.h"
#include "nsigner_client.h"
#include "../cjson/cJSON.h"

int main(int argc, char **argv) {
    const char *socket_name = "nsigner";
    const char *event_json = "{\"kind\":1,\"content\":\"hello from client example\",\"tags\":[],\"created_at\":1700000000}";
    const char *role = "main";
    nsigner_transport_t *transport = NULL;
    nsigner_client_t *client = NULL;
    cJSON *params = NULL;
    cJSON *opts = NULL;
    cJSON *result = NULL;
    cJSON *response = NULL;
    char *response_json = NULL;
    int rc = 1;

    if (argc > 1 && argv[1] != NULL && argv[1][0] != '\0') {
        socket_name = argv[1];
    }

    if (nostr_init() != NOSTR_SUCCESS) {
        fprintf(stderr, "failed to initialize crypto subsystem\n");
        return 1;
    }

    transport = nsigner_transport_open_unix(socket_name, 5000);
    if (transport == NULL) {
        fprintf(stderr, "connect failed: cannot open unix transport @%s\n", socket_name);
        goto cleanup;
    }

    client = nsigner_client_new(transport);
    if (client == NULL) {
        fprintf(stderr, "connect failed: cannot create nsigner client\n");
        transport->close(transport);
        goto cleanup;
    }
    transport = NULL; /* owned by client now */

    /* params: [ "<event_json>", {"role":"main"} ] */
    params = cJSON_CreateArray();
    if (params == NULL) {
        fprintf(stderr, "out of memory\n");
        goto cleanup;
    }
    cJSON_AddItemToArray(params, cJSON_CreateString(event_json));

    opts = cJSON_CreateObject();
    if (opts == NULL) {
        fprintf(stderr, "out of memory\n");
        goto cleanup;
    }
    if (role != NULL && role[0] != '\0') {
        cJSON_AddStringToObject(opts, "role", role);
    }
    cJSON_AddItemToArray(params, opts);
    opts = NULL; /* owned by params now */

    if (nsigner_client_call(client, "sign_event", params, &result) != NOSTR_SUCCESS) {
        fprintf(stderr, "request failed: %s\n", nsigner_client_last_error(client));
        goto cleanup;
    }
    params = NULL; /* nsigner_client_call takes ownership of params */

    /*
     * Reconstruct a JSON-RPC response string for backward-compatible CLI
     * output: {"id":"1","result":"<signed event json>"}
     * The server returns the signed event as a JSON string (not an object),
     * so result is a cJSON string here.
     */
    response = cJSON_CreateObject();
    if (response == NULL) {
        fprintf(stderr, "out of memory\n");
        goto cleanup;
    }
    cJSON_AddStringToObject(response, "id", "1");
    cJSON_AddItemReferenceToObject(response, "result", result);

    response_json = cJSON_PrintUnformatted(response);
    if (response_json == NULL) {
        fprintf(stderr, "failed to serialize response\n");
        goto cleanup;
    }

    printf("%s\n", response_json);
    rc = 0;

cleanup:
    free(response_json);
    cJSON_Delete(response);
    cJSON_Delete(result);
    cJSON_Delete(params);
    cJSON_Delete(opts);
    nsigner_client_free(client); /* also closes/frees the transport */
    nostr_cleanup();
    return rc;
}
