package protocol

import (
	"crypto/sha1"
	"crypto/sha512"
	"encoding/hex"
	"strings"
	"testing"

	"filippo.io/edwards25519"
)

// Helper to match ts3j hex string decoding
func hexBytes(s string) []byte {
	b, _ := hex.DecodeString(s)
	return b
}

func TestCryptoInit2_Ts3jVectors(t *testing.T) {
	// Vectors from ts3j CryptoInit2Test.java
	licenseBytes := hexBytes("0100358541498A24ACD30157918B8F50955C0DAE970AB65372CBE407" +
		"415FCF3E029B02084D15E00AA793600700000020416E6F6E796D6F7573000047D9E4DC25AA2E90ACD4DB5FA61C8F" +
		"ED369B346D84C2CA2FCCCA86F73AFEF092200A77C8810A787141")
	alpha := hexBytes("9500A5DB3B50ACECAB81")
	beta := hexBytes("EAFFC9A8BC996B25C8AA700264E99E372ECCDEB1C121D6EC0F4D49FB46" +
		"CEEBA4E3C724B3070FD70CB03D7BC08129205690ECE228CA7C")
	privateKeyBytes := hexBytes("102E591ABA4508129E812FF3437E2DDD3CA1F1EC341117CA35" +
		"14CC347A7C2A77")

	expectedIvStructHex := "E4082A92F71C96A947452F5582EF2879B2051ED2D3" +
		"F2C6B0643CF5A266EE6B5180573C2F5F3F1C4AC579188366F16AE0EADC3AAF860805D8F2A831E9E49F4513"
	expectedFakeSigHex := "54F2B4D661E0F9AB"

	// 1. Derive Server Public Key (License)
	serverPubBytes, err := ParseLicenseAndDeriveKey(licenseBytes)
	if err != nil {
		t.Fatalf("ParseLicenseAndDeriveKey failed: %v", err)
	}

	// 2. Derive Shared Secret (simulating ts3j generateSharedSecret2)

	// Load Server Point
	serverPoint, err := new(edwards25519.Point).SetBytes(serverPubBytes)
	if err != nil {
		t.Fatalf("Invalid server pub key derived: %v", err)
	}

	// Negate Server Point
	serverPoint.Negate(serverPoint)

	// Create Scalar from private key
	scalarBytes := make([]byte, 32)
	copy(scalarBytes, privateKeyBytes)
	scalarBytes[31] &= 0x7F // ts3j specific masking

	// Load Scalar
	scalar, err := new(edwards25519.Scalar).SetBytesWithClamping(scalarBytes)
	if err != nil {
		t.Fatalf("Scalar load failed: %v", err)
	}

	// Multiply
	sharedPoint := new(edwards25519.Point).ScalarMult(scalar, serverPoint)
	sharedBytes := sharedPoint.Bytes()

	// Flip Sign
	sharedBytes[31] ^= 0x80

	// Hash
	sharedSecret := sha512.Sum512(sharedBytes)

	// 3. Calculate IV/Mac
	// IV = XOR(SharedSecret, Alpha) ++ XOR(SharedSecret, Beta)
	ivStruct := make([]byte, 64)
	copy(ivStruct, sharedSecret[:])

	for i := 0; i < 10; i++ {
		ivStruct[i] ^= alpha[i]
	}
	if len(beta) < 54 {
		t.Fatal("Beta too short")
	}
	for i := 0; i < 54; i++ {
		ivStruct[10+i] ^= beta[i]
	}

	// FakeSig = SHA1(IV)[0..8]
	macHash := sha1.Sum(ivStruct)
	fakeSig := macHash[0:8]

	// Compare
	gotIvHex := hex.EncodeToString(ivStruct)
	if !strings.EqualFold(gotIvHex, expectedIvStructHex) {
		t.Errorf("IV Struct Mismatch.\nGot:  %s\nWant: %s", gotIvHex, expectedIvStructHex)
	}

	gotSigHex := hex.EncodeToString(fakeSig)
	if !strings.EqualFold(gotSigHex, expectedFakeSigHex) {
		t.Errorf("FakeSig Mismatch.\nGot:  %s\nWant: %s", gotSigHex, expectedFakeSigHex)
	}
}
