/*
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE
 * file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
 * to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
 * License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */
package org.apache.tuweni.crypto;

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.apache.tuweni.bytes.Bytes.fromHexString;
import static org.junit.jupiter.api.Assertions.*;

import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.crypto.SECP256K1.KeyPair;
import org.apache.tuweni.crypto.SECP256K1.PublicKey;
import org.apache.tuweni.crypto.SECP256K1.SecretKey;
import org.apache.tuweni.crypto.SECP256K1.Signature;
import org.apache.tuweni.junit.BouncyCastleExtension;
import org.apache.tuweni.junit.TempDirectory;
import org.apache.tuweni.junit.TempDirectoryExtension;

import java.math.BigInteger;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Random;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;

@ExtendWith(TempDirectoryExtension.class)
@ExtendWith(BouncyCastleExtension.class)
class SECP256K1Test {

  @Test
  void testCreatePrivateKey_NullEncoding() {
    assertThrows(NullPointerException.class, () -> SecretKey.fromBytes(null));
  }

  @Test
  void testPrivateKeyEquals() {
    SecretKey secretKey1 = SecretKey.fromInteger(BigInteger.TEN);
    SecretKey secretKey2 = SecretKey.fromInteger(BigInteger.TEN);
    assertEquals(secretKey1, secretKey2);
  }

  @Test
  void testPrivateHashCode() {
    SecretKey secretKey = SecretKey.fromInteger(BigInteger.TEN);
    assertNotEquals(0, secretKey.hashCode());
  }

  @Test
  void testCreatePublicKey_NullEncoding() {
    assertThrows(NullPointerException.class, () -> SECP256K1.PublicKey.fromBytes(null));
  }

  @Test
  void testCreatePublicKey_EncodingTooShort() {
    assertThrows(IllegalArgumentException.class, () -> SECP256K1.PublicKey.fromBytes(Bytes.wrap(new byte[63])));
  }

  @Test
  void testCreatePublicKey_EncodingTooLong() {
    assertThrows(IllegalArgumentException.class, () -> SECP256K1.PublicKey.fromBytes(Bytes.wrap(new byte[65])));
  }

  @Test
  void testPublicKeyEquals() {
    SECP256K1.PublicKey publicKey1 = SECP256K1.PublicKey.fromBytes(
        fromHexString(
            "a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7893aba425419bc27a3b6c7e693a24c696f794c2ed877a1593cbee53b037368d7"));
    SECP256K1.PublicKey publicKey2 = SECP256K1.PublicKey.fromBytes(
        fromHexString(
            "a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7893aba425419bc27a3b6c7e693a24c696f794c2ed877a1593cbee53b037368d7"));
    assertEquals(publicKey1, publicKey2);
  }

  @Test
  void testPublicHashCode() {
    SECP256K1.PublicKey publicKey = SECP256K1.PublicKey.fromBytes(
        fromHexString(
            "a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7893aba425419bc27a3b6c7e693a24c696f794c2ed877a1593cbee53b037368d7"));

    assertNotEquals(0, publicKey.hashCode());
  }

  @Test
  void testCreateKeyPair_PublicKeyNull() {
    assertThrows(
        NullPointerException.class,
        () -> SECP256K1.KeyPair.create(null, SECP256K1.PublicKey.fromBytes(Bytes.wrap(new byte[64]))));
  }

  @Test
  void testCreateKeyPair_PrivateKeyNull() {
    assertThrows(
        NullPointerException.class,
        () -> SECP256K1.KeyPair.create(SecretKey.fromBytes(Bytes32.wrap(new byte[32])), null));
  }

  @Test
  void testKeyPairGeneration() {
    SECP256K1.KeyPair keyPair = SECP256K1.KeyPair.random();
    assertNotNull(keyPair);
    assertNotNull(keyPair.secretKey());
    assertNotNull(keyPair.publicKey());
  }

  @Test
  void testKeyPairEquals() {
    SecretKey secretKey1 = SecretKey.fromInteger(BigInteger.TEN);
    SecretKey secretKey2 = SecretKey.fromInteger(BigInteger.TEN);
    SECP256K1.PublicKey publicKey1 = SECP256K1.PublicKey.fromBytes(
        fromHexString(
            "a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7893aba425419bc27a3b6c7e693a24c696f794c2ed877a1593cbee53b037368d7"));
    SECP256K1.PublicKey publicKey2 = SECP256K1.PublicKey.fromBytes(
        fromHexString(
            "a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7893aba425419bc27a3b6c7e693a24c696f794c2ed877a1593cbee53b037368d7"));

    SECP256K1.KeyPair keyPair1 = SECP256K1.KeyPair.create(secretKey1, publicKey1);
    SECP256K1.KeyPair keyPair2 = SECP256K1.KeyPair.create(secretKey2, publicKey2);

    assertEquals(keyPair1, keyPair2);
  }

  @Test
  void testKeyPairHashCode() {
    SECP256K1.KeyPair keyPair = SECP256K1.KeyPair.random();
    assertNotEquals(0, keyPair.hashCode());
  }

  @Test
  void testKeyPairGeneration_PublicKeyRecovery() {
    SECP256K1.KeyPair keyPair = SECP256K1.KeyPair.random();
    assertEquals(keyPair.publicKey(), SECP256K1.PublicKey.fromSecretKey(keyPair.secretKey()));
  }

  @Test
  void testPublicKeyRecovery() {
    SecretKey secretKey = SecretKey.fromInteger(BigInteger.TEN);
    SECP256K1.PublicKey expectedPublicKey = SECP256K1.PublicKey.fromBytes(
        fromHexString(
            "a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7893aba425419bc27a3b6c7e693a24c696f794c2ed877a1593cbee53b037368d7"));

    SECP256K1.PublicKey publicKey = SECP256K1.PublicKey.fromSecretKey(secretKey);
    assertEquals(expectedPublicKey, publicKey);
  }

  @Test
  void testCreateSignature() {
    SECP256K1.Signature signature = new SECP256K1.Signature((byte) 0, BigInteger.ONE, BigInteger.TEN);
    assertEquals(BigInteger.ONE, signature.r());
    assertEquals(BigInteger.TEN, signature.s());
    assertEquals((byte) 0, signature.v());
  }

  @Test
  void testEncodeSignature() {
    SECP256K1.Signature signature = new SECP256K1.Signature((byte) 0, BigInteger.ONE, BigInteger.TEN);
    assertEquals(
        "0x0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000A00",
        signature.bytes().toString());
  }

  @Test
  void testCreateSignatureFromEncoding() {
    SECP256K1.Signature signature = SECP256K1.Signature.fromBytes(
        fromHexString(
            "0x0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000A01"));
    assertEquals(BigInteger.ONE, signature.r());
    assertEquals(BigInteger.TEN, signature.s());
    assertEquals((byte) 1, signature.v());
  }

  @Test
  void testCreateSignatureWithNullR() {
    assertThrows(NullPointerException.class, () -> SECP256K1.Signature.create((byte) 1, null, BigInteger.ONE));
  }

  @Test
  void testCreateSignatureWithNullS() {
    assertThrows(NullPointerException.class, () -> SECP256K1.Signature.create((byte) 1, BigInteger.ONE, null));
  }

  @Test
  void testCreateSignatureWithZeroR() {
    Exception throwable = assertThrows(
        IllegalArgumentException.class,
        () -> SECP256K1.Signature.create((byte) 1, BigInteger.ZERO, BigInteger.ONE));
    assertEquals(
        "Invalid r-value, should be >= 1 and < " + SECP256K1.Parameters.CURVE.getN() + ", got 0",
        throwable.getMessage());
  }

  @Test
  void testCreateSignatureWithZeroS() {
    Exception throwable = assertThrows(
        IllegalArgumentException.class,
        () -> SECP256K1.Signature.create((byte) 1, BigInteger.ONE, BigInteger.ZERO));
    assertEquals(
        "Invalid s-value, should be >= 1 and < " + SECP256K1.Parameters.CURVE.getN() + ", got 0",
        throwable.getMessage());
  }

  @Test
  void testCreateSignatureWithRHigherThanCurve() {
    BigInteger curveN = SECP256K1.Parameters.CURVE.getN();
    Exception throwable = assertThrows(
        IllegalArgumentException.class,
        () -> SECP256K1.Signature.create((byte) 1, curveN.add(BigInteger.ONE), BigInteger.ONE));
    assertEquals(
        "Invalid r-value, should be >= 1 and < " + curveN + ", got " + curveN.add(BigInteger.ONE),
        throwable.getMessage());
  }

  @Test
  void testCreateSignatureWithSHigherThanCurve() {
    BigInteger curveN = SECP256K1.Parameters.CURVE.getN();
    Exception throwable = assertThrows(
        IllegalArgumentException.class,
        () -> SECP256K1.Signature.create((byte) 1, BigInteger.ONE, curveN.add(BigInteger.ONE)));
    assertEquals(
        "Invalid s-value, should be >= 1 and < " + curveN + ", got " + curveN.add(BigInteger.ONE),
        throwable.getMessage());
  }

  @Test
  void testRecoverPublicKeyFromSignature() {
    SecretKey secretKey =
        SecretKey.fromInteger(new BigInteger("c85ef7d79691fe79573b1a7064c19c1a9819ebdbd1faaab1a8ec92344438aaf4", 16));
    SECP256K1.KeyPair keyPair = SECP256K1.KeyPair.fromSecretKey(secretKey);

    long seed = new Random().nextLong();
    Random random = new Random(seed);
    for (int i = 0; i < 100; ++i) {
      try {
        byte[] data = new byte[20];
        random.nextBytes(data);
        SECP256K1.Signature signature = SECP256K1.sign(data, keyPair);

        PublicKey recoveredPublicKey = SECP256K1.PublicKey.recoverFromSignature(data, signature);
        assertNotNull(recoveredPublicKey);
        assertEquals(keyPair.publicKey().toString(), recoveredPublicKey.toString());
        assertTrue(SECP256K1.verify(data, signature, recoveredPublicKey));
      } catch (AssertionError e) {
        System.err.println("Random seed: " + seed);
        throw e;
      }
    }

    Bytes32 hash = Bytes32.fromHexString("ACB1C19AC0832320815B5E886C6B73AD7D6177853D44B026F2A7A9E11BB899FC");
    SECP256K1.Signature signature = SECP256K1.Signature.create(
        (byte) 1,
        new BigInteger("62380806879052346173879701944100777919767605075819957043497305774369260714318"),
        new BigInteger("38020116821208196490118623452490256423459205241616519723877133146103446128360"));
    assertNull(SECP256K1.PublicKey.recoverFromHashAndSignature(hash, signature));
  }

  @Test
  void testCannotRecoverPublicKeyFromSignature() {
    SECP256K1.Signature signature =
        new Signature((byte) 0, SECP256K1.Parameters.CURVE_ORDER.subtract(BigInteger.ONE), BigInteger.valueOf(10));
    assertNull(SECP256K1.PublicKey.recoverFromSignature(Bytes.of("Random data".getBytes(UTF_8)), signature));
  }

  @Test
  void testSignatureGeneration() {
    SecretKey secretKey =
        SecretKey.fromInteger(new BigInteger("c85ef7d79691fe79573b1a7064c19c1a9819ebdbd1faaab1a8ec92344438aaf4", 16));
    SECP256K1.KeyPair keyPair = SECP256K1.KeyPair.fromSecretKey(secretKey);

    Bytes data = Bytes.wrap("This is an example of a signed message.".getBytes(UTF_8));
    SECP256K1.Signature expectedSignature = new SECP256K1.Signature(
        (byte) 1,
        new BigInteger("d2ce488f4da29e68f22cb05cac1b19b75df170a12b4ad1bdd4531b8e9115c6fb", 16),
        new BigInteger("75c1fe50a95e8ccffcbb5482a1e42fbbdd6324131dfe75c3b3b7f9a7c721eccb", 16));

    SECP256K1.Signature actualSignature = SECP256K1.sign(data, keyPair);
    assertEquals(expectedSignature, actualSignature);
  }

  @Test
  void testSignatureVerification() {
    SecretKey secretKey =
        SecretKey.fromInteger(new BigInteger("c85ef7d79691fe79573b1a7064c19c1a9819ebdbd1faaab1a8ec92344438aaf4", 16));
    SECP256K1.KeyPair keyPair = SECP256K1.KeyPair.fromSecretKey(secretKey);

    Bytes data = Bytes.wrap("This is an example of a signed message.".getBytes(UTF_8));

    SECP256K1.Signature signature = SECP256K1.sign(data, keyPair);
    assertTrue(SECP256K1.verify(data, signature, keyPair.publicKey()));
  }

  @Test
  void testFileContainsValidPrivateKey(@TempDirectory Path tempDir) throws Exception {
    Path tempFile = tempDir.resolve("tempId");
    Files.write(tempFile, "000000000000000000000000000000000000000000000000000000000000000A".getBytes(UTF_8));
    SecretKey secretKey = SecretKey.load(tempFile);
    assertEquals(fromHexString("000000000000000000000000000000000000000000000000000000000000000A"), secretKey.bytes());
  }

  @Test
  void testReadWritePrivateKeyString(@TempDirectory Path tempDir) throws Exception {
    SecretKey secretKey = SecretKey.fromInteger(BigInteger.TEN);
    SECP256K1.KeyPair keyPair1 = SECP256K1.KeyPair.fromSecretKey(secretKey);
    Path tempFile = tempDir.resolve("tempId");
    keyPair1.store(tempFile);
    SECP256K1.KeyPair keyPair2 = SECP256K1.KeyPair.load(tempFile);
    assertEquals(keyPair1, keyPair2);
  }

  @Test
  void testInvalidFileThrowsInvalidKeyPairException(@TempDirectory Path tempDir) throws Exception {
    Path tempFile = tempDir.resolve("tempId");
    Files.write(tempFile, "not valid".getBytes(UTF_8));
    assertThrows(InvalidSEC256K1SecretKeyStoreException.class, () -> SecretKey.load(tempFile));
  }

  @Test
  void testInvalidMultiLineFileThrowsInvalidIdException(@TempDirectory Path tempDir) throws Exception {
    Path tempFile = tempDir.resolve("tempId");
    Files.write(tempFile, "not\n\nvalid".getBytes(UTF_8));
    assertThrows(InvalidSEC256K1SecretKeyStoreException.class, () -> SecretKey.load(tempFile));
  }

  @Test
  void testEncodedBytes() {
    KeyPair kp = SECP256K1.KeyPair.random();
    Signature sig = SECP256K1.sign(Bytes.of(1, 2, 3), kp);
    assertEquals(65, sig.bytes().size());
    assertTrue(sig.bytes().get(64) <= 3 && sig.bytes().get(64) >= 0);
  }

  @Test
  void testSharedSecretBytes() {
    KeyPair kp = SECP256K1.KeyPair.random();
    KeyPair otherKP = SECP256K1.KeyPair.random();
    Bytes32 sharedSecret = SECP256K1.calculateKeyAgreement(kp.secretKey(), otherKP.publicKey());
    Bytes32 otherSharedSecret = SECP256K1.calculateKeyAgreement(otherKP.secretKey(), kp.publicKey());
    assertEquals(sharedSecret, otherSharedSecret);
  }
}
