#!/usr/bin/env node

// Spec-compliant test to send config_query command with proper NIP-44 encryption
// Uses nostr-tools for encryption and event creation

import { nip44, finalizeEvent, getPublicKey } from 'nostr-tools';
import WebSocket from 'ws';

// Test keys from make_and_restart_relay.sh -t
const ADMIN_PRIVATE_KEY = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
const ADMIN_PUBLIC_KEY = "6a04ab98d9e4774ad806e302dddeb63bea16b5cb5f223ee77478e861bb583eb3";
const RELAY_PUBLIC_KEY = "4f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa";
const RELAY_URL = "ws://localhost:8888";

async function main() {
    console.log("=== Testing Admin API Config Query (Spec Compliant) ===");
    console.log("Sending config_query command using nostr-tools...");

    // Command array as per README.md spec
    const commandArray = ["config_query", "all"];
    const commandJson = JSON.stringify(commandArray);

    console.log(`Command: ${commandJson}`);

    return new Promise((resolve, reject) => {
        const ws = new WebSocket(RELAY_URL);
        let queryResponseReceived = false;

        ws.on('open', () => {
            console.log("WebSocket connected");

            try {
                const adminPubkey = getPublicKey(Buffer.from(ADMIN_PRIVATE_KEY, 'hex'));
                console.log(`Admin pubkey: ${adminPubkey}`);

                // Send subscription for response events
                const subId = "admin_response";
                const subMessage = JSON.stringify(["REQ", subId, { kinds: [23457], "#p": [ADMIN_PUBLIC_KEY] }]);
                ws.send(subMessage);
                console.log(`Subscription sent: ${subMessage}`);

                // Send the first command
                sendCommand(ws, commandArray);

            } catch (error) {
                console.error("Failed to prepare/send command:", error.message);
                ws.close();
                reject(error);
            }
        });

        ws.on('message', (data) => {
            const message = data.toString();
            console.log(`Relay response: ${message}`);

            try {
                const parsed = JSON.parse(message);
                if (parsed[0] === "EVENT" && parsed[1] === "admin_response") {
                    const event = parsed[2];
                    if (event.kind === 23457) {
                        // Decrypt the response content
                        const conversationKey = nip44.getConversationKey(Buffer.from(ADMIN_PRIVATE_KEY, 'hex'), RELAY_PUBLIC_KEY);
                        const decrypted = nip44.decrypt(event.content, conversationKey);
                        console.log(`Decrypted response: ${decrypted}`);

                        if (!queryResponseReceived) {
                            queryResponseReceived = true;
                            console.log("\n=== Testing Admin API Config Update ===");
                            console.log("Sending config_update command to change relay_description...");

                            // Send the second command
                            const updateCommandArray = ["config_update", [{"key": "relay_description", "value": "Bozo the clown", "data_type": "string", "category": "relay"}]];
                            sendCommand(ws, updateCommandArray);
                        }
                    }
                }
            } catch (error) {
                // Ignore parsing errors
            }
        });

        ws.on('error', (error) => {
            console.error("WebSocket error:", error.message);
            reject(error);
        });

        ws.on('close', () => {
            console.log("WebSocket closed");
            resolve();
        });

        // Timeout after 20 seconds
        setTimeout(() => {
            ws.close();
        }, 20000);
    });
}

function sendCommand(ws, commandArray) {
    try {
        const commandJson = JSON.stringify(commandArray);
        console.log(`Command: ${commandJson}`);

        // Derive conversation key for NIP-44 encryption
        const conversationKey = nip44.getConversationKey(Buffer.from(ADMIN_PRIVATE_KEY, 'hex'), RELAY_PUBLIC_KEY);

        // Encrypt the command JSON with NIP-44
        const encryptedContent = nip44.encrypt(commandJson, conversationKey);
        console.log(`Encrypted content: ${encryptedContent.substring(0, 50)}...`);

        // Create the event template
        const eventTemplate = {
            kind: 23456,
            created_at: Math.floor(Date.now() / 1000),
            tags: [['p', RELAY_PUBLIC_KEY]],
            content: encryptedContent
        };

        // Sign the event
        const event = finalizeEvent(eventTemplate, Buffer.from(ADMIN_PRIVATE_KEY, 'hex'));
        console.log(`Event sent: ${JSON.stringify(event, null, 2)}`);

        // Send the event
        const eventMessage = JSON.stringify(["EVENT", event]);
        ws.send(eventMessage);
        console.log("Command sent successfully!");
        console.log("Listening for responses...");

    } catch (error) {
        console.error("Failed to send command:", error.message);
        ws.close();
    }
}

main().catch(console.error);