/*
 * NOSTR Core Library - NIP-006: Key Derivation from Mnemonic
 */

#include "nip006.h"
#include "utils.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include "../nostr_core/nostr_common.h"

int nostr_generate_keypair(unsigned char* private_key, unsigned char* public_key) {
    if (!private_key || !public_key) {
        return NOSTR_ERROR_INVALID_INPUT;
    }
    
    // Generate random entropy using /dev/urandom
    FILE* urandom = fopen("/dev/urandom", "rb");
    if (!urandom) {
        return NOSTR_ERROR_IO_FAILED;
    }
    
    if (fread(private_key, 1, 32, urandom) != 32) {
        fclose(urandom);
        return NOSTR_ERROR_IO_FAILED;
    }
    fclose(urandom);
    
    // Validate private key
    if (nostr_ec_private_key_verify(private_key) != 0) {
        return NOSTR_ERROR_CRYPTO_FAILED;
    }
    
    // Generate public key from private key (already x-only for NOSTR)
    if (nostr_ec_public_key_from_private_key(private_key, public_key) != 0) {
        return NOSTR_ERROR_CRYPTO_FAILED;
    }
    
    return NOSTR_SUCCESS;
}

int nostr_generate_mnemonic_and_keys(char* mnemonic, size_t mnemonic_size, 
                                    int account, unsigned char* private_key, 
                                    unsigned char* public_key) {
    if (!mnemonic || mnemonic_size < 256 || !private_key || !public_key) {
        return NOSTR_ERROR_INVALID_INPUT;
    }
    
    // Generate entropy for 12-word mnemonic
    unsigned char entropy[16];
    FILE* urandom = fopen("/dev/urandom", "rb");
    if (!urandom) {
        return NOSTR_ERROR_IO_FAILED;
    }
    
    if (fread(entropy, 1, sizeof(entropy), urandom) != sizeof(entropy)) {
        fclose(urandom);
        return NOSTR_ERROR_IO_FAILED;
    }
    fclose(urandom);
    
    // Generate mnemonic from entropy
    if (nostr_bip39_mnemonic_from_bytes(entropy, sizeof(entropy), mnemonic) != 0) {
        return NOSTR_ERROR_CRYPTO_FAILED;
    }
    
    // Derive keys from the generated mnemonic
    return nostr_derive_keys_from_mnemonic(mnemonic, account, private_key, public_key);
}

int nostr_derive_keys_from_mnemonic(const char* mnemonic, int account,
                                   unsigned char* private_key, unsigned char* public_key) {
    if (!mnemonic || !private_key || !public_key) {
        return NOSTR_ERROR_INVALID_INPUT;
    }
    
    // Validate mnemonic
    if (nostr_bip39_mnemonic_validate(mnemonic) != 0) {
        return NOSTR_ERROR_INVALID_INPUT;
    }
    
    // Convert mnemonic to seed
    unsigned char seed[64];
    if (nostr_bip39_mnemonic_to_seed(mnemonic, "", seed, sizeof(seed)) != 0) {
        return NOSTR_ERROR_CRYPTO_FAILED;
    }
    
    // Derive master key from seed
    nostr_hd_key_t master_key;
    if (nostr_bip32_key_from_seed(seed, sizeof(seed), &master_key) != 0) {
        return NOSTR_ERROR_CRYPTO_FAILED;
    }
    
    // NIP-06 path: m/44'/1237'/account'/0/0
    nostr_hd_key_t derived_key;
    uint32_t path[] = {
        0x80000000 + 44,    // 44' (hardened)
        0x80000000 + 1237,  // 1237' (hardened)
        0x80000000 + account, // account' (hardened)
        0,                   // 0 (not hardened)
        0                    // 0 (not hardened)
    };
    
    if (nostr_bip32_derive_path(&master_key, path, sizeof(path) / sizeof(path[0]), &derived_key) != 0) {
        return NOSTR_ERROR_CRYPTO_FAILED;
    }
    
    // Extract private key and public key
    memcpy(private_key, derived_key.private_key, 32);
    memcpy(public_key, derived_key.public_key + 1, 32); // Remove compression prefix for x-only
    
    return NOSTR_SUCCESS;
}

// Note: nostr_detect_input_type, nostr_decode_nsec, and nostr_decode_npub
// are implemented in NIP-019 to avoid multiple definitions
