package bip85

import (
	"bytes"
	"encoding/hex"
	"fmt"
	"strings"
	"testing"

	"github.com/tyler-smith/go-bip39"
)

const (
	// Test master BIP32 root key from the BIP85 specification
	testMasterKey = "xprv9s21ZrQH143K2LBWUUQRFXhucrQqBpKdRRxNVq2zBqsx8HVqFk2uYo8kmbaLLHRdqtQpUm98uKfu3vca1LqdGhUtyoFnCNkfmXRyPXLjbKb"

	// Test Case 1 - Basic entropy derivation with path m/83696968'/0'/0'
	testCase1Path               = "m/83696968'/0'/0'"
	testCase1ExpectedDerivedKey = "cca20ccb0e9a90feb0912870c3323b24874b0ca3d8018c4b96d0b97c0e82ded0"
	testCase1ExpectedEntropy    = "efecfbccffea313214232d29e71563d941229afb4338c21f9517c41aaa0d16f00b83d2a09ef747e7a64e8e2bd5a14869e693da66ce94ac2da570ab7ee48618f7"

	// Test Case 2 - Basic entropy derivation with path m/83696968'/0'/1'
	testCase2Path               = "m/83696968'/0'/1'"
	testCase2ExpectedDerivedKey = "503776919131758bb7de7beb6c0ae24894f4ec042c26032890c29359216e21ba"
	testCase2ExpectedEntropy    = "70c6e3e8ebee8dc4c0dbba66076819bb8c09672527c4277ca8729532ad711872218f826919f6b67218adde99018a6df9095ab2b58d803b5b93ec9802085a690e"

	// BIP85-DRNG-SHAKE256 test vector
	drngTestPath        = "m/83696968'/0'/0'"
	drngExpected80Bytes = "b78b1ee6b345eae6836c2d53d33c64cdaf9a696487be81b03e822dc84b3f1cd883d7559e53d175f243e4c349e822a957bbff9224bc5dde9492ef54e8a439f6bc8c7355b87a925a37ee405a7502991111"

	// Python DRNG test vectors
	pythonDRNG50BytesExpected  = "b78b1ee6b345eae6836c2d53d33c64cdaf9a696487be81b03e822dc84b3f1cd883d7559e53d175f243e4c349e822a957bbff"
	pythonDRNG100BytesExpected = "9224bc5dde9492ef54e8a439f6bc8c7355b87a925a37ee405a7502991111cd2dddaf1883f4e962abf4fb4b31cd28d5cf6b14f6ddcc9c19fd56d7f960a4b27f1d423a55dda4865aa6ddd6b4c26f18d400bb0a593e6c785d6d7e28c9c64608624318eddc01"
	pythonDRNG150BytesExpected = "23750caa2a271f35faa6a3ca292b4be357404eca6842c69a3717dc3e41f7b38c67be492395b32221470aa08a2c489018c635a175f731245330e1f47091dbfb26f2923d10bd2e09280bffd1d94eb2a88f964aeb1774da04aad3bb1fdde0f77cd5ca79617ae317375417a51339523057bebef434c4400303890332e458425242f56a4293dad4f632b82713467b18ed6e1dab633220523d"
	pythonDRNG20BytesExpected  = "b78b1ee6b345eae6836c2d53d33c64cdaf9a6964"
	pythonDRNG25BytesExpected  = "87be81b03e822dc84b3f1cd883d7559e53d175f243e4c349e8"

	// BIP39 12 English words test vector
	bip39_12WordsPath             = "m/83696968'/39'/0'/12'/0'"
	bip39_12WordsExpectedEntropy  = "6250b68daf746d12a24d58b4787a714b"
	bip39_12WordsExpectedMnemonic = "girl mad pet galaxy egg matter matrix prison refuse sense ordinary nose"

	// BIP39 18 English words test vector
	bip39_18WordsPath             = "m/83696968'/39'/0'/18'/0'"
	bip39_18WordsExpectedEntropy  = "938033ed8b12698449d4bbca3c853c66b293ea1b1ce9d9dc"
	bip39_18WordsExpectedMnemonic = "near account window bike charge season chef number sketch tomorrow excuse sniff circle vital hockey outdoor supply token"

	// BIP39 24 English words test vector
	bip39_24WordsPath             = "m/83696968'/39'/0'/24'/0'"
	bip39_24WordsExpectedEntropy  = "ae131e2312cdc61331542efe0d1077bac5ea803adf24b313a4f0e48e9c51f37f"
	bip39_24WordsExpectedMnemonic = "puppy ocean match cereal symbol another shed magic wrap hammer bulb intact gadget divorce twin tonight reason outdoor destroy simple truth cigar social volcano"

	// HD-Seed WIF test vector
	hdWifPath            = "m/83696968'/2'/0'"
	hdWifExpectedEntropy = "7040bb53104f27367f317558e78a994ada7296c6fde36a364e5baf206e502bb1"
	hdWifExpectedWIF     = "Kzyv4uF39d4Jrw2W7UryTHwZr1zQVNk4dAFyqE6BuMrMh1Za7uhp"

	// XPRV test vector
	xprvPath        = "m/83696968'/32'/0'"
	xprvExpectedKey = "xprv9s21ZrQH143K2srSbCSg4m4kLvPMzcWydgmKEnMmoZUurYuBuYG46c6P71UGXMzmriLzCCBvKQWBUv3vPB3m1SATMhp3uEjXHJ42jFg7myX"

	// HEX test vector
	hexPath            = "m/83696968'/128169'/64'/0'"
	hexExpectedEntropy = "492db4698cf3b73a5a24998aa3e9d7fa96275d85724a91e71aa2d645442f878555d078fd1f1f67e368976f04137b1f7a0d19232136ca50c44614af72b5582a5c"

	// PWD Base64 test vector
	pwdBase64Path             = "m/83696968'/707764'/21'/0'"
	pwdBase64ExpectedEntropy  = "74a2e87a9ba0cdd549bdd2f9ea880d554c6c355b08ed25088cfa88f3f1c4f74632b652fd4a8f5fda43074c6f6964a3753b08bb5210c8f5e75c07a4c2a20bf6e9"
	pwdBase64ExpectedPassword = "dKLoepugzdVJvdL56ogNV"

	// PWD Base85 test vector
	pwdBase85Path             = "m/83696968'/707785'/12'/0'"
	pwdBase85ExpectedEntropy  = "f7cfe56f63dca2490f65fcbf9ee63dcd85d18f751b6b5e1c1b8733af6459c904a75e82b4a22efff9b9e69de2144b293aa8714319a054b6cb55826a8e51425209"
	pwdBase85ExpectedPassword = "_s`{TW89)i4`"

	// Test keys for parsing tests
	testInvalidMasterKey = "xprv9s21ZrQH143K2LBWUUQRFXhucrQqBpKdRRxNVq2zBqsx8HVqFk2uYo8kmbaLLHRdqtQpUm98uKfu3vca1LqdGhUtyoFnCNkfmXRyPXLjbXX"
	testTestnetMasterKey = "tprv8ZgxMBicQKsPeWHBt7a68nPnvgTnuDhUgDWC8wZCgA8GahrQ3f3uWpq7wE7Uc1dLBnCe1hhCZ886K6ND37memRDWqsA9HgSKDXtwh2Qxo6J"
)

// logTestVector logs test information in a cleaner, more concise format
func logTestVector(t *testing.T, title, description string) {
	t.Logf("=== TEST: %s ===", title)
}

// TestDerivedKey is a helper function to test the derived key directly
func TestDerivedKey(t *testing.T) {
	logTestVector(t, "Derived Child Keys", "Testing direct key derivation for BIP85 paths")

	masterKey, err := ParseMasterKey(testMasterKey)
	if err != nil {
		t.Fatalf("Failed to parse master key: %v", err)
	}

	// Test case 1
	t.Logf("Deriving key for path: %s", testCase1Path)
	derivedKeyBytes, err := DeriveChildKey(masterKey, testCase1Path)
	if err != nil {
		t.Fatalf("Failed to derive child key: %v", err)
	}

	derivedKeyHex := hex.EncodeToString(derivedKeyBytes)
	t.Logf("EXPECTED: %s", testCase1ExpectedDerivedKey)
	t.Logf("ACTUAL:   %s", derivedKeyHex)

	if derivedKeyHex != testCase1ExpectedDerivedKey {
		t.Errorf("Expected derived key bytes %s, got %s", testCase1ExpectedDerivedKey, derivedKeyHex)
	} else {
		t.Logf("RESULT: PASS ✓")
	}

	// Test case 2
	t.Logf("Deriving key for path: %s", testCase2Path)
	derivedKeyBytes, err = DeriveChildKey(masterKey, testCase2Path)
	if err != nil {
		t.Fatalf("Failed to derive child key: %v", err)
	}

	derivedKeyHex = hex.EncodeToString(derivedKeyBytes)
	t.Logf("EXPECTED: %s", testCase2ExpectedDerivedKey)
	t.Logf("ACTUAL:   %s", derivedKeyHex)

	if derivedKeyHex != testCase2ExpectedDerivedKey {
		t.Errorf("Expected derived key bytes %s, got %s", testCase2ExpectedDerivedKey, derivedKeyHex)
	} else {
		t.Logf("RESULT: PASS ✓")
	}
}

// TestCase1 tests the first test vector from the BIP85 specification
func TestCase1(t *testing.T) {
	logTestVector(t, "Test Case 1", "Basic entropy derivation with path m/83696968'/0'/0'")

	masterKey, err := ParseMasterKey(testMasterKey)
	if err != nil {
		t.Fatalf("Failed to parse master key: %v", err)
	}

	t.Logf("Test path: %s", testCase1Path)
	entropy, err := DeriveBIP85Entropy(masterKey, testCase1Path)
	if err != nil {
		t.Fatalf("Failed to derive entropy: %v", err)
	}

	derivedEntropyHex := hex.EncodeToString(entropy)
	t.Logf("EXPECTED: %s", testCase1ExpectedEntropy)
	t.Logf("ACTUAL:   %s", derivedEntropyHex)

	if derivedEntropyHex != testCase1ExpectedEntropy {
		t.Errorf("Expected derived entropy %s, got %s", testCase1ExpectedEntropy, derivedEntropyHex)
	} else {
		t.Logf("RESULT: PASS ✓")
	}
}

// TestCase2 tests the second test vector from the BIP85 specification
func TestCase2(t *testing.T) {
	logTestVector(t, "Test Case 2", "Basic entropy derivation with path m/83696968'/0'/1'")

	masterKey, err := ParseMasterKey(testMasterKey)
	if err != nil {
		t.Fatalf("Failed to parse master key: %v", err)
	}

	t.Logf("Test path: %s", testCase2Path)
	entropy, err := DeriveBIP85Entropy(masterKey, testCase2Path)
	if err != nil {
		t.Fatalf("Failed to derive entropy: %v", err)
	}

	derivedEntropyHex := hex.EncodeToString(entropy)
	t.Logf("EXPECTED: %s", testCase2ExpectedEntropy)
	t.Logf("ACTUAL:   %s", derivedEntropyHex)

	if derivedEntropyHex != testCase2ExpectedEntropy {
		t.Errorf("Expected derived entropy %s, got %s", testCase2ExpectedEntropy, derivedEntropyHex)
	} else {
		t.Logf("RESULT: PASS ✓")
	}
}

// TestBIP39_12EnglishWords tests the BIP39 12 English words test vector
func TestBIP39_12EnglishWords(t *testing.T) {
	logTestVector(t, "BIP39 12 English Words", "Deriving a 12-word English BIP39 mnemonic")

	masterKey, err := ParseMasterKey(testMasterKey)
	if err != nil {
		t.Fatalf("Failed to parse master key: %v", err)
	}

	t.Logf("Path: %s", bip39_12WordsPath)
	t.Logf("Parameters: Language=English(0), Words=12, Index=0")

	// BIP39 English 12 word mnemonic
	entropy, err := DeriveBIP39Entropy(masterKey, 0, 12, 0)
	if err != nil {
		t.Fatalf("Failed to derive BIP39 entropy: %v", err)
	}

	derivedEntropyHex := hex.EncodeToString(entropy)
	t.Logf("EXPECTED ENTROPY: %s", bip39_12WordsExpectedEntropy)
	t.Logf("ACTUAL ENTROPY:   %s", derivedEntropyHex)

	if derivedEntropyHex != bip39_12WordsExpectedEntropy {
		t.Errorf("Expected derived entropy %s, got %s", bip39_12WordsExpectedEntropy, derivedEntropyHex)
	} else {
		t.Logf("ENTROPY MATCH: PASS ✓")
	}

	// Convert entropy to mnemonic
	mnemonic, err := bip39.NewMnemonic(entropy)
	if err != nil {
		t.Fatalf("Failed to create mnemonic: %v", err)
	}

	t.Logf("EXPECTED MNEMONIC: %s", bip39_12WordsExpectedMnemonic)
	t.Logf("ACTUAL MNEMONIC:   %s", mnemonic)

	if mnemonic != bip39_12WordsExpectedMnemonic {
		t.Errorf("Expected mnemonic '%s', got '%s'", bip39_12WordsExpectedMnemonic, mnemonic)
	} else {
		t.Logf("MNEMONIC MATCH: PASS ✓")
	}
}

// TestBIP39_18EnglishWords tests the BIP39 18 English words test vector
func TestBIP39_18EnglishWords(t *testing.T) {
	logTestVector(t, "BIP39 18 English Words", "Deriving an 18-word English BIP39 mnemonic")

	masterKey, err := ParseMasterKey(testMasterKey)
	if err != nil {
		t.Fatalf("Failed to parse master key: %v", err)
	}

	t.Logf("Path: %s", bip39_18WordsPath)
	t.Logf("Parameters: Language=English(0), Words=18, Index=0")

	// BIP39 English 18 word mnemonic
	entropy, err := DeriveBIP39Entropy(masterKey, 0, 18, 0)
	if err != nil {
		t.Fatalf("Failed to derive BIP39 entropy: %v", err)
	}

	derivedEntropyHex := hex.EncodeToString(entropy)
	t.Logf("EXPECTED ENTROPY: %s", bip39_18WordsExpectedEntropy)
	t.Logf("ACTUAL ENTROPY:   %s", derivedEntropyHex)

	if derivedEntropyHex != bip39_18WordsExpectedEntropy {
		t.Errorf("Expected derived entropy %s, got %s", bip39_18WordsExpectedEntropy, derivedEntropyHex)
	} else {
		t.Logf("ENTROPY MATCH: PASS ✓")
	}

	// Convert entropy to mnemonic
	mnemonic, err := bip39.NewMnemonic(entropy)
	if err != nil {
		t.Fatalf("Failed to create mnemonic: %v", err)
	}

	t.Logf("EXPECTED MNEMONIC: %s", bip39_18WordsExpectedMnemonic)
	t.Logf("ACTUAL MNEMONIC:   %s", mnemonic)

	if mnemonic != bip39_18WordsExpectedMnemonic {
		t.Errorf("Expected mnemonic '%s', got '%s'", bip39_18WordsExpectedMnemonic, mnemonic)
	} else {
		t.Logf("MNEMONIC MATCH: PASS ✓")
	}
}

// TestBIP39_24EnglishWords tests the BIP39 24 English words test vector
func TestBIP39_24EnglishWords(t *testing.T) {
	logTestVector(t, "BIP39 24 English Words", "Deriving a 24-word English BIP39 mnemonic")

	masterKey, err := ParseMasterKey(testMasterKey)
	if err != nil {
		t.Fatalf("Failed to parse master key: %v", err)
	}

	t.Logf("Path: %s", bip39_24WordsPath)
	t.Logf("Parameters: Language=English(0), Words=24, Index=0")

	// BIP39 English 24 word mnemonic
	entropy, err := DeriveBIP39Entropy(masterKey, 0, 24, 0)
	if err != nil {
		t.Fatalf("Failed to derive BIP39 entropy: %v", err)
	}

	derivedEntropyHex := hex.EncodeToString(entropy)
	t.Logf("EXPECTED ENTROPY: %s", bip39_24WordsExpectedEntropy)
	t.Logf("ACTUAL ENTROPY:   %s", derivedEntropyHex)

	if derivedEntropyHex != bip39_24WordsExpectedEntropy {
		t.Errorf("Expected derived entropy %s, got %s", bip39_24WordsExpectedEntropy, derivedEntropyHex)
	} else {
		t.Logf("ENTROPY MATCH: PASS ✓")
	}

	// Convert entropy to mnemonic
	mnemonic, err := bip39.NewMnemonic(entropy)
	if err != nil {
		t.Fatalf("Failed to create mnemonic: %v", err)
	}

	t.Logf("EXPECTED MNEMONIC: %s", bip39_24WordsExpectedMnemonic)
	t.Logf("ACTUAL MNEMONIC:   %s", mnemonic)

	if mnemonic != bip39_24WordsExpectedMnemonic {
		t.Errorf("Expected mnemonic '%s', got '%s'", bip39_24WordsExpectedMnemonic, mnemonic)
	} else {
		t.Logf("MNEMONIC MATCH: PASS ✓")
	}
}

// TestHD_WIF tests the WIF test vector
func TestHD_WIF(t *testing.T) {
	logTestVector(t, "HD-Seed WIF", "Deriving a WIF-encoded private key for Bitcoin Core hdseed")

	masterKey, err := ParseMasterKey(testMasterKey)
	if err != nil {
		t.Fatalf("Failed to parse master key: %v", err)
	}

	// First verify the entropy derivation
	t.Logf("Path: %s", hdWifPath)

	entropy, err := DeriveBIP85Entropy(masterKey, hdWifPath)
	if err != nil {
		t.Fatalf("Failed to derive entropy: %v", err)
	}

	// Expected entropy from BIP85 spec
	derivedEntropyHex := hex.EncodeToString(entropy[:32]) // WIF uses first 32 bytes

	if derivedEntropyHex != hdWifExpectedEntropy {
		t.Errorf("Entropy mismatch!\nExpected: %s\nGot:      %s", hdWifExpectedEntropy, derivedEntropyHex)
	}

	// Now test the WIF derivation
	wif, err := DeriveWIFKey(masterKey, 0)
	if err != nil {
		t.Fatalf("Failed to derive WIF key: %v", err)
	}

	t.Logf("EXPECTED WIF: %s", hdWifExpectedWIF)
	t.Logf("ACTUAL WIF:   %s", wif)

	if wif != hdWifExpectedWIF {
		t.Errorf("Expected WIF %s, got %s", hdWifExpectedWIF, wif)
	} else {
		t.Logf("RESULT: PASS ✓")
	}
}

// TestXPRV tests the XPRV test vector
func TestXPRV(t *testing.T) {
	logTestVector(t, "XPRV", "Deriving an extended private key (XPRV)")

	masterKey, err := ParseMasterKey(testMasterKey)
	if err != nil {
		t.Fatalf("Failed to parse master key: %v", err)
	}

	t.Logf("Path: %s", xprvPath)
	derivedKey, err := DeriveXPRV(masterKey, 0)
	if err != nil {
		t.Fatalf("Failed to derive XPRV: %v", err)
	}

	derivedXPRV := derivedKey.String()
	t.Logf("EXPECTED XPRV: %s", xprvExpectedKey)
	t.Logf("ACTUAL XPRV:   %s", derivedXPRV)

	if derivedXPRV != xprvExpectedKey {
		t.Errorf("Expected XPRV %s, got %s", xprvExpectedKey, derivedXPRV)
	} else {
		t.Logf("RESULT: PASS ✓")
	}
}

// TestDRNG_SHAKE256 tests the BIP85-DRNG-SHAKE256 test vector
func TestDRNG_SHAKE256(t *testing.T) {
	logTestVector(t, "DRNG-SHAKE256", "Testing the deterministic random number generator with SHAKE256")

	masterKey, err := ParseMasterKey(testMasterKey)
	if err != nil {
		t.Fatalf("Failed to parse master key: %v", err)
	}

	// Derive entropy for the DRNG
	entropy, err := DeriveBIP85Entropy(masterKey, drngTestPath)
	if err != nil {
		t.Fatalf("Failed to derive entropy: %v", err)
	}

	// Create DRNG
	drng := NewBIP85DRNG(entropy)

	// Read 80 bytes
	buffer := make([]byte, 80)
	n, err := drng.Read(buffer)
	if err != nil {
		t.Fatalf("Failed to read from DRNG: %v", err)
	}
	if n != 80 {
		t.Errorf("Expected to read 80 bytes, got %d", n)
	}

	hexOutput := hex.EncodeToString(buffer)

	if !strings.EqualFold(hexOutput, drngExpected80Bytes) {
		t.Errorf("Expected DRNG output:\n%s\n\nGot:\n%s", drngExpected80Bytes, hexOutput)
	}
}

// TestPythonDRNGVectors tests the DRNG vectors from the Python implementation
func TestPythonDRNGVectors(t *testing.T) {
	logTestVector(t, "Python DRNG Vectors", "Testing specific DRNG vectors from the Python implementation")

	masterKey, err := ParseMasterKey(testMasterKey)
	if err != nil {
		t.Fatalf("Failed to parse master key: %v", err)
	}

	// Derive entropy for the DRNG
	entropy, err := DeriveBIP85Entropy(masterKey, drngTestPath)
	if err != nil {
		t.Fatalf("Failed to derive entropy: %v", err)
	}

	// Create DRNG
	drng := NewBIP85DRNG(entropy)

	// Test vector 1: Read 50 bytes
	buffer1 := make([]byte, 50)
	_, err = drng.Read(buffer1)
	if err != nil {
		t.Fatalf("Failed to read 50 bytes from DRNG: %v", err)
	}
	actual1 := hex.EncodeToString(buffer1)
	if actual1 != pythonDRNG50BytesExpected {
		t.Errorf("Test vector 1 failed. Expected:\n%s\n\nGot:\n%s", pythonDRNG50BytesExpected, actual1)
	}

	// Test vector 2: Read 100 bytes
	buffer2 := make([]byte, 100)
	_, err = drng.Read(buffer2)
	if err != nil {
		t.Fatalf("Failed to read 100 bytes from DRNG: %v", err)
	}
	actual2 := hex.EncodeToString(buffer2)
	if actual2 != pythonDRNG100BytesExpected {
		t.Errorf("Test vector 2 failed. Expected:\n%s\n\nGot:\n%s", pythonDRNG100BytesExpected, actual2)
	}

	// Test vector 3: Read 150 bytes
	buffer3 := make([]byte, 150)
	_, err = drng.Read(buffer3)
	if err != nil {
		t.Fatalf("Failed to read 150 bytes from DRNG: %v", err)
	}
	actual3 := hex.EncodeToString(buffer3)
	if actual3 != pythonDRNG150BytesExpected {
		t.Errorf("Test vector 3 failed. Expected:\n%s\n\nGot:\n%s", pythonDRNG150BytesExpected, actual3)
	}

	// Test with fresh DRNG
	drng2 := NewBIP85DRNG(entropy)
	buffer4 := make([]byte, 20)
	_, err = drng2.Read(buffer4)
	if err != nil {
		t.Fatalf("Failed to read 20 bytes from DRNG: %v", err)
	}
	actual4 := hex.EncodeToString(buffer4)
	if actual4 != pythonDRNG20BytesExpected {
		t.Errorf("Test vector 4 failed. Expected:\n%s\n\nGot:\n%s", pythonDRNG20BytesExpected, actual4)
	}

	// Read another 25 bytes
	buffer5 := make([]byte, 25)
	_, err = drng2.Read(buffer5)
	if err != nil {
		t.Fatalf("Failed to read 25 bytes from DRNG: %v", err)
	}
	actual5 := hex.EncodeToString(buffer5)
	if actual5 != pythonDRNG25BytesExpected {
		t.Errorf("Test vector 5 failed. Expected:\n%s\n\nGot:\n%s", pythonDRNG25BytesExpected, actual5)
	}
}

// TestDRNGDeterminism tests the deterministic behavior of the DRNG
func TestDRNGDeterminism(t *testing.T) {
	logTestVector(t, "DRNG Determinism", "Testing deterministic behavior of the DRNG")

	masterKey, err := ParseMasterKey(testMasterKey)
	if err != nil {
		t.Fatalf("Failed to parse master key: %v", err)
	}

	// Derive entropy for the DRNG
	entropy, err := DeriveBIP85Entropy(masterKey, drngTestPath)
	if err != nil {
		t.Fatalf("Failed to derive entropy: %v", err)
	}

	// Create 3 DRNGs with the same seed
	drng1 := NewBIP85DRNG(entropy)
	drng2 := NewBIP85DRNG(entropy)
	drng3 := NewBIP85DRNG(entropy)

	// Read from drng1 with multiple calls
	buf1a := make([]byte, 10)
	buf1b := make([]byte, 20)
	buf1c := make([]byte, 30)
	buf1d := make([]byte, 40)
	_, err = drng1.Read(buf1a)
	if err != nil {
		t.Fatalf("Failed to read from drng1: %v", err)
	}
	_, err = drng1.Read(buf1b)
	if err != nil {
		t.Fatalf("Failed to read from drng1: %v", err)
	}
	_, err = drng1.Read(buf1c)
	if err != nil {
		t.Fatalf("Failed to read from drng1: %v", err)
	}
	_, err = drng1.Read(buf1d)
	if err != nil {
		t.Fatalf("Failed to read from drng1: %v", err)
	}

	// Read from drng2 with multiple calls in different order
	buf2a := make([]byte, 40)
	buf2b := make([]byte, 30)
	buf2c := make([]byte, 20)
	buf2d := make([]byte, 10)
	_, err = drng2.Read(buf2a)
	if err != nil {
		t.Fatalf("Failed to read from drng2: %v", err)
	}
	_, err = drng2.Read(buf2b)
	if err != nil {
		t.Fatalf("Failed to read from drng2: %v", err)
	}
	_, err = drng2.Read(buf2c)
	if err != nil {
		t.Fatalf("Failed to read from drng2: %v", err)
	}
	_, err = drng2.Read(buf2d)
	if err != nil {
		t.Fatalf("Failed to read from drng2: %v", err)
	}

	// Read from drng3 with a single call
	buf3 := make([]byte, 100)
	_, err = drng3.Read(buf3)
	if err != nil {
		t.Fatalf("Failed to read from drng3: %v", err)
	}

	// Combine the results from the multiple reads
	result1 := append(append(append(buf1a, buf1b...), buf1c...), buf1d...)
	result2 := append(append(append(buf2a, buf2b...), buf2c...), buf2d...)

	// All results should be identical
	if !bytes.Equal(result1, result2) {
		t.Errorf("Expected drng1 and drng2 to produce identical outputs")
	}
	if !bytes.Equal(result2, buf3) {
		t.Errorf("Expected drng2 and drng3 to produce identical outputs")
	}
}

// TestDRNGLengths tests the DRNG with different lengths
func TestDRNGLengths(t *testing.T) {
	logTestVector(t, "DRNG Lengths", "Testing DRNG with different read lengths")

	masterKey, err := ParseMasterKey(testMasterKey)
	if err != nil {
		t.Fatalf("Failed to parse master key: %v", err)
	}

	// Derive entropy for the DRNG
	entropy, err := DeriveBIP85Entropy(masterKey, drngTestPath)
	if err != nil {
		t.Fatalf("Failed to derive entropy: %v", err)
	}

	// Create DRNG
	drng := NewBIP85DRNG(entropy)

	// Test various lengths
	lengths := []int{1, 10, 100, 1000, 10000}
	for _, length := range lengths {
		buffer := make([]byte, length)
		n, err := drng.Read(buffer)
		if err != nil {
			t.Errorf("Failed to read %d bytes: %v", length, err)
			continue
		}
		if n != length {
			t.Errorf("Expected to read %d bytes, got %d", length, n)
		}
	}
}

// TestDRNGExceptions tests error handling in the DRNG
func TestDRNGExceptions(t *testing.T) {
	logTestVector(t, "DRNG Exceptions", "Testing error handling in the DRNG")

	// Test with entropy of the wrong size
	testCases := []int{0, 1, 32, 63, 65, 128}

	for _, size := range testCases {
		t.Run(fmt.Sprintf("EntropySize_%d", size), func(t *testing.T) {
			entropy := make([]byte, size)

			// Use a function to capture the panic
			testPanic := func() {
				defer func() {
					if r := recover(); r != nil {
						// Expected behavior - panic occurred
						return
					}
				}()

				// This should panic for any size != 64
				_ = NewBIP85DRNG(entropy)

				// If we get here without panic, it's an error
				t.Errorf("Expected panic for entropy length %d, but it didn't happen", size)
			}

			testPanic()
		})
	}
}

// TestDRNGDifferentSizes tests the DRNG with different buffer sizes
func TestDRNGDifferentSizes(t *testing.T) {
	logTestVector(t, "DRNG Different Sizes", "Testing the DRNG with different buffer sizes")

	masterKey, err := ParseMasterKey(testMasterKey)
	if err != nil {
		t.Fatalf("Failed to parse master key: %v", err)
	}

	entropy, err := DeriveBIP85Entropy(masterKey, drngTestPath)
	if err != nil {
		t.Fatalf("Failed to derive entropy: %v", err)
	}

	// Create DRNG
	drng := NewBIP85DRNG(entropy)

	// Test reading different sizes
	for _, size := range []int{32, 64, 128, 256} {
		buffer := make([]byte, size)
		n, err := drng.Read(buffer)
		if err != nil {
			t.Fatalf("Failed to read %d bytes from DRNG: %v", size, err)
		}
		if n != size {
			t.Errorf("Expected to read %d bytes, got %d", size, n)
		}
	}

	// Test deterministic behavior - two DRNGs with the same seed should produce the same output
	drng1 := NewBIP85DRNG(entropy)
	drng2 := NewBIP85DRNG(entropy)

	buffer1 := make([]byte, 32)
	buffer2 := make([]byte, 32)

	_, err = drng1.Read(buffer1)
	if err != nil {
		t.Fatalf("Failed to read from first DRNG: %v", err)
	}

	_, err = drng2.Read(buffer2)
	if err != nil {
		t.Fatalf("Failed to read from second DRNG: %v", err)
	}

	if !bytes.Equal(buffer1, buffer2) {
		t.Errorf("Expected identical outputs from DRNGs with same seed")
	}

	// Reading another 32 bytes should produce different output from the first read
	buffer3 := make([]byte, 32)
	_, err = drng1.Read(buffer3)
	if err != nil {
		t.Fatalf("Failed to read second buffer from DRNG: %v", err)
	}

	if bytes.Equal(buffer1, buffer3) {
		t.Errorf("Expected different outputs from sequential reads")
	}
}

// TestMasterKeyParsing tests parsing of different master key formats
func TestMasterKeyParsing(t *testing.T) {
	logTestVector(t, "Master Key Parsing", "Testing parsing of master keys in different formats")

	// Test valid master key
	t.Logf("Testing valid master key")
	_, err := ParseMasterKey(testMasterKey)
	if err != nil {
		t.Errorf("Failed to parse valid master key: %v", err)
	} else {
		t.Logf("Valid master key parsed successfully: PASS ✓")
	}

	// Test invalid master key (wrong checksum)
	t.Logf("Testing invalid master key (corrupted)")
	_, err = ParseMasterKey(testInvalidMasterKey)
	if err == nil {
		t.Errorf("Expected error for invalid master key, but got nil")
	} else {
		t.Logf("Got expected error for invalid master key: %v", err)
		t.Logf("RESULT: PASS ✓")
	}

	// Test testnet master key (tprv)
	t.Logf("Testing testnet master key format")
	testnetMasterKey, err := ParseMasterKey(testTestnetMasterKey)
	if err != nil {
		t.Errorf("Failed to parse testnet master key: %v", err)
	} else {
		t.Logf("Testnet master key parsed successfully: PASS ✓")

		// Test that XPRV derivation using a testnet master key produces a testnet XPRV
		derivedKey, err := DeriveXPRV(testnetMasterKey, 0)
		if err != nil {
			t.Fatalf("Failed to derive XPRV from testnet key: %v", err)
		}

		derivedKeyStr := derivedKey.String()
		if !strings.HasPrefix(derivedKeyStr, "tprv") {
			t.Errorf("Expected derived key to be testnet (tprv prefix), got: %s", derivedKeyStr)
		} else {
			t.Logf("Testnet XPRV derived successfully: %s", derivedKeyStr)
			t.Logf("RESULT: PASS ✓")
		}
	}
}

// TestDifferentPathFormats tests different path format expressions
func TestDifferentPathFormats(t *testing.T) {
	logTestVector(t, "Path Formats", "Testing different path format expressions")

	masterKey, err := ParseMasterKey(testMasterKey)
	if err != nil {
		t.Fatalf("Failed to parse master key: %v", err)
	}

	// Define equivalent paths in different formats
	paths := []string{
		"m/83696968'/0'/0'",
		"m/83696968h/0h/0h",
		"/83696968'/0'/0'",
		"83696968'/0'/0'",
	}

	var results [][]byte

	// Derive entropy using each path
	for i, path := range paths {
		t.Logf("Testing path format %d: %s", i+1, path)
		entropy, err := DeriveBIP85Entropy(masterKey, path)
		if err != nil {
			t.Errorf("Failed to derive entropy with path %s: %v", path, err)
			continue
		}

		results = append(results, entropy)
		t.Logf("Derivation succeeded: PASS ✓")
	}

	// Verify all results are the same
	for i := 1; i < len(results); i++ {
		if !bytes.Equal(results[0], results[i]) {
			t.Errorf("Path %s produced different entropy than path %s", paths[0], paths[i])
		}
	}

	if len(results) > 1 {
		t.Logf("All equivalent path formats produced the same entropy: PASS ✓")
	}
}

// TestDirectBase85Encoding tests direct Base85 encoding with the test vector entropy
func TestDirectBase85Encoding(t *testing.T) {
	logTestVector(t, "Direct Base85 Encoding", "Testing Base85 encoding with BIP85 test vector")

	// Parse the master key
	masterKey, err := ParseMasterKey(testMasterKey)
	if err != nil {
		t.Fatalf("Failed to parse master key: %v", err)
	}

	// First, derive the entropy and verify it matches the test vector
	derivedEntropy, err := DeriveBIP85Entropy(masterKey, pwdBase85Path)
	if err != nil {
		t.Fatalf("Failed to derive entropy: %v", err)
	}

	// This is the expected entropy from the BIP85 spec for the Base85 test vector
	expectedEntropy, err := hex.DecodeString(pwdBase85ExpectedEntropy)
	if err != nil {
		t.Fatalf("Failed to decode expected entropy hex: %v", err)
	}

	// Verify the derived entropy matches the expected entropy
	derivedEntropyHex := hex.EncodeToString(derivedEntropy)
	if derivedEntropyHex != pwdBase85ExpectedEntropy {
		t.Errorf("Entropy mismatch!\nExpected: %s\nGot:      %s", pwdBase85ExpectedEntropy, derivedEntropyHex)
	}

	// Verify the entropy bytes match
	if !bytes.Equal(derivedEntropy, expectedEntropy) {
		t.Errorf("Entropy bytes do not match the test vector")
	}

	// Now test the password generation
	pwd, err := DeriveBase85Password(masterKey, 12, 0)
	if err != nil {
		t.Fatalf("Failed to derive Base85 password: %v", err)
	}

	// Expected password from the test vector
	if pwd != pwdBase85ExpectedPassword {
		t.Errorf("Password mismatch!\nExpected: '%s'\nGot:      '%s'", pwdBase85ExpectedPassword, pwd)
	}
}

// TestPWDBase64 tests the Base64 password test vector
func TestPWDBase64(t *testing.T) {
	logTestVector(t, "PWD Base64", "Deriving a Base64-encoded password")

	masterKey, err := ParseMasterKey(testMasterKey)
	if err != nil {
		t.Fatalf("Failed to parse master key: %v", err)
	}

	// Testing with the example from the BIP85 spec - 21 characters
	t.Logf("Path: %s", pwdBase64Path)
	t.Logf("Parameters: Length=21, Index=0")

	// First verify the entropy derivation
	entropy, err := DeriveBIP85Entropy(masterKey, pwdBase64Path)
	if err != nil {
		t.Fatalf("Failed to derive entropy: %v", err)
	}

	// Expected entropy from BIP85 spec
	derivedEntropyHex := hex.EncodeToString(entropy)

	if derivedEntropyHex != pwdBase64ExpectedEntropy {
		t.Errorf("Entropy mismatch!\nExpected: %s\nGot:      %s", pwdBase64ExpectedEntropy, derivedEntropyHex)
	}

	// Now test the password generation
	pwd, err := DeriveBase64Password(masterKey, 21, 0)
	if err != nil {
		t.Fatalf("Failed to derive Base64 password: %v", err)
	}

	// The test vector from the BIP85 specification
	t.Logf("EXPECTED PASSWORD: %s", pwdBase64ExpectedPassword)
	t.Logf("ACTUAL PASSWORD:   %s", pwd)

	if pwd != pwdBase64ExpectedPassword {
		t.Errorf("Expected password '%s', got '%s'", pwdBase64ExpectedPassword, pwd)
	} else {
		t.Logf("RESULT: PASS ✓")
	}

	t.Logf("Password length: %d characters", len(pwd))
}

// TestPWDBase85 tests the Base85 password test vector
func TestPWDBase85(t *testing.T) {
	logTestVector(t, "PWD Base85", "Deriving a Base85-encoded password")

	masterKey, err := ParseMasterKey(testMasterKey)
	if err != nil {
		t.Fatalf("Failed to parse master key: %v", err)
	}

	// Testing with the example from the BIP85 spec - 12 characters
	t.Logf("Path: %s", pwdBase85Path)
	t.Logf("Parameters: Length=12, Index=0")

	// First verify the entropy derivation
	entropy, err := DeriveBIP85Entropy(masterKey, pwdBase85Path)
	if err != nil {
		t.Fatalf("Failed to derive entropy: %v", err)
	}

	// Expected entropy from BIP85 spec
	derivedEntropyHex := hex.EncodeToString(entropy)

	if derivedEntropyHex != pwdBase85ExpectedEntropy {
		t.Errorf("Entropy mismatch!\nExpected: %s\nGot:      %s", pwdBase85ExpectedEntropy, derivedEntropyHex)
	}

	// Now test the password generation
	pwd, err := DeriveBase85Password(masterKey, 12, 0)
	if err != nil {
		t.Fatalf("Failed to derive Base85 password: %v", err)
	}

	// The test vector from the BIP85 specification
	t.Logf("EXPECTED PASSWORD: %s", pwdBase85ExpectedPassword)
	t.Logf("ACTUAL PASSWORD:   %s", pwd)

	if pwd != pwdBase85ExpectedPassword {
		t.Errorf("Expected password '%s', got '%s'", pwdBase85ExpectedPassword, pwd)
	} else {
		t.Logf("RESULT: PASS ✓")
	}

	t.Logf("Password length: %d characters", len(pwd))
}

// TestHexDerivation tests the HEX derivation test vector
func TestHexDerivation(t *testing.T) {
	logTestVector(t, "HEX Derivation", "Testing HEX data derivation with BIP85 test vector")

	masterKey, err := ParseMasterKey(testMasterKey)
	if err != nil {
		t.Fatalf("Failed to parse master key: %v", err)
	}

	// Test vector from BIP85 spec
	t.Logf("Path: %s", hexPath)
	t.Logf("Parameters: NumBytes=64, Index=0")

	// First verify the entropy derivation
	entropy, err := DeriveBIP85Entropy(masterKey, hexPath)
	if err != nil {
		t.Fatalf("Failed to derive entropy: %v", err)
	}

	// Expected entropy from BIP85 spec
	derivedEntropyHex := hex.EncodeToString(entropy[:64]) // HEX uses first 64 bytes

	if derivedEntropyHex != hexExpectedEntropy {
		t.Errorf("Entropy mismatch!\nExpected: %s\nGot:      %s", hexExpectedEntropy, derivedEntropyHex)
	}

	// Now test the hex derivation
	hexData, err := DeriveHex(masterKey, 64, 0)
	if err != nil {
		t.Fatalf("Failed to derive hex data: %v", err)
	}

	if hexData != hexExpectedEntropy {
		t.Errorf("Hex data mismatch!\nExpected: %s\nGot:      %s", hexExpectedEntropy, hexData)
	}
}

// TestInvalidParameters tests error conditions for parameter validation
func TestInvalidParameters(t *testing.T) {
	logTestVector(t, "Invalid Parameters", "Testing error handling for invalid inputs")

	masterKey, err := ParseMasterKey(testMasterKey)
	if err != nil {
		t.Fatalf("Failed to parse master key: %v", err)
	}

	// Test cases for parameter validation
	testCases := []struct {
		name     string
		testFunc func() error
	}{
		{
			name: "BIP39 invalid word count",
			testFunc: func() error {
				_, err := DeriveBIP39Entropy(masterKey, 0, 13, 0) // 13 is not valid (must be 12, 15, 18, 21, 24)
				return err
			},
		},
		{
			name: "Base64 password too short",
			testFunc: func() error {
				_, err := DeriveBase64Password(masterKey, 19, 0) // Min is 20
				return err
			},
		},
		{
			name: "Base64 password too long",
			testFunc: func() error {
				_, err := DeriveBase64Password(masterKey, 87, 0) // Max is 86
				return err
			},
		},
		{
			name: "Base85 password too short",
			testFunc: func() error {
				_, err := DeriveBase85Password(masterKey, 9, 0) // Min is 10
				return err
			},
		},
		{
			name: "Base85 password too long",
			testFunc: func() error {
				_, err := DeriveBase85Password(masterKey, 81, 0) // Max is 80
				return err
			},
		},
		{
			name: "Hex data too small",
			testFunc: func() error {
				_, err := DeriveHex(masterKey, 15, 0) // Min is 16
				return err
			},
		},
		{
			name: "Hex data too large",
			testFunc: func() error {
				_, err := DeriveHex(masterKey, 65, 0) // Max is 64
				return err
			},
		},
	}

	// Run all validation test cases
	for _, tc := range testCases {
		t.Logf("Testing: %s", tc.name)
		err := tc.testFunc()
		if err == nil {
			t.Errorf("Expected error for %s, but got nil", tc.name)
		} else {
			t.Logf("Got expected error: %v", err)
			t.Logf("RESULT: PASS ✓")
		}
	}
}

// TestAdditionalDeriveHex tests additional hex derivation scenarios
func TestAdditionalDeriveHex(t *testing.T) {
	logTestVector(t, "Additional Hex Derivation", "Testing hex data derivation with various lengths")

	masterKey, err := ParseMasterKey(testMasterKey)
	if err != nil {
		t.Fatalf("Failed to parse master key: %v", err)
	}

	// Test min size (16 bytes)
	hexMinBytes, err := DeriveHex(masterKey, 16, 0)
	if err != nil {
		t.Fatalf("Failed to derive 16-byte hex: %v", err)
	}
	t.Logf("16-byte hex: %s", hexMinBytes)
	if len(hexMinBytes) != 32 { // 16 bytes = 32 hex chars
		t.Errorf("Expected 32 hex chars (16 bytes), got %d chars", len(hexMinBytes))
	} else {
		t.Logf("RESULT: PASS ✓")
	}

	// Test max size (64 bytes)
	hexMaxBytes, err := DeriveHex(masterKey, 64, 0)
	if err != nil {
		t.Fatalf("Failed to derive 64-byte hex: %v", err)
	}
	t.Logf("64-byte hex: %s", hexMaxBytes)
	if len(hexMaxBytes) != 128 { // 64 bytes = 128 hex chars
		t.Errorf("Expected 128 hex chars (64 bytes), got %d chars", len(hexMaxBytes))
	} else {
		t.Logf("RESULT: PASS ✓")
	}

	// Test different index values
	hex1, err := DeriveHex(masterKey, 32, 0)
	if err != nil {
		t.Fatalf("Failed to derive hex with index 0: %v", err)
	}

	hex2, err := DeriveHex(masterKey, 32, 1)
	if err != nil {
		t.Fatalf("Failed to derive hex with index 1: %v", err)
	}

	t.Logf("Hex index 0: %s", hex1)
	t.Logf("Hex index 1: %s", hex2)

	if hex1 == hex2 {
		t.Errorf("Expected different hex values for different indexes")
	} else {
		t.Logf("Different indexes produced different outputs: PASS ✓")
	}
}
