// ECDSA signing and verification for P-256 (FIPS 186-4).
// Uses RFC 6979 deterministic nonce generation.

/// ECDSA key pair.
pub struct ECDSAKeyPair {
  /// Private key scalar (32 bytes, big-endian).
  private_key : Array[UInt]
  /// Public key as uncompressed point (65 bytes: 0x04 || x || y).
  public_key : Array[UInt]
}

/// ECDSA signature (r, s) each 32 bytes big-endian.
pub(all) struct ECDSASignature {
  r : Array[UInt]
  s : Array[UInt]
}

fn bytes_to_uint_array(bytes : Bytes) -> Array[UInt] {
  let arr : Array[UInt] = []
  for i in 0.. Bytes {
  let buf : Array[Byte] = []
  for value in values {
    buf.push((value & 0xFFU).to_byte())
  }
  Bytes::from_array(buf)
}

/// Generate key pair from a 32-byte private key.
pub fn ecdsa_keygen(private_key_bytes : Array[UInt]) -> Result[ECDSAKeyPair, String] {
  if private_key_bytes.length() != 32 {
    return Err("Private key must be 32 bytes")
  }
  let d = sc_from_bytes(private_key_bytes)
  if !sc_is_valid(d) {
    return Err("Private key out of range")
  }

  // Q = d * G
  let q = point_mul(d, point_generator())
  let q_affine = point_to_affine(q)
  if q_affine.infinity {
    return Err("Invalid private key (produces identity)")
  }

  let pub_key : Array[UInt] = []
  pub_key.push(0x04U) // uncompressed point prefix
  let x_bytes = fe_to_bytes(q_affine.x)
  let y_bytes = fe_to_bytes(q_affine.y)
  for v in x_bytes {
    pub_key.push(v)
  }
  for v in y_bytes {
    pub_key.push(v)
  }

  Ok(ECDSAKeyPair::{ private_key: private_key_bytes, public_key: pub_key })
}

/// Parse a public key from uncompressed format (65 bytes: 0x04 || x || y).
fn parse_public_key(pub_key : Array[UInt]) -> Result[ProjectivePoint, String] {
  if pub_key.length() != 65 || pub_key[0] != 0x04U {
    return Err("Invalid public key format (expected uncompressed)")
  }
  let x_bytes : Array[UInt] = []
  let y_bytes : Array[UInt] = []
  for i in 1..<33 {
    x_bytes.push(pub_key[i])
  }
  for i in 33..<65 {
    y_bytes.push(pub_key[i])
  }
  let x = fe_from_bytes(x_bytes)
  let y = fe_from_bytes(y_bytes)

  // Verify point is on curve: y^2 = x^3 + ax + b (mod p)
  let x_mont = fe_to_mont(x)
  let y_mont = fe_to_mont(y)
  let y2 = fe_sqr(y_mont)
  let x2 = fe_sqr(x_mont)
  let x3 = fe_mul(x2, x_mont)
  let ax = fe_mul(get_curve_a_mont(), x_mont)
  let rhs = fe_add(fe_add(x3, ax), get_curve_b_mont())
  if !fe_eq(y2, rhs) {
    return Err("Point not on curve")
  }

  Ok(ProjectivePoint::{ x: x_mont, y: y_mont, z: fe_copy(field_one) })
}

/// RFC 6979 deterministic nonce generation for ECDSA.
/// Produces a deterministic k value from the private key and message hash.
fn rfc6979_generate_k(
  private_key : Array[UInt],
  hash : FixedArray[UInt],
) -> FixedArray[UInt] {
  // hash is 32 bytes (SHA-256 output) as FixedArray[UInt]
  let hash_arr : Array[UInt] = []
  for i in 0.. Result[ECDSASignature, String] {
  if private_key.length() != 32 {
    return Err("Private key must be 32 bytes")
  }
  if message_hash.length() != 32 {
    return Err("Message hash must be 32 bytes (SHA-256)")
  }

  let d = sc_from_bytes(private_key)
  if !sc_is_valid(d) {
    return Err("Private key out of range")
  }

  // z = message hash as scalar (truncated to n bits if needed, but SHA-256 is 256 bits = n bits)
  let z_bytes : Array[UInt] = []
  for i in 0.. Result[ECDSASignature, String] {
  let hash = @sha2.Sha256::digest(message)
  ecdsa_sign(private_key, hash)
}

/// Verify an ECDSA signature against a message hash and public key.
pub fn ecdsa_verify(
  public_key : Array[UInt],
  message_hash : FixedArray[UInt],
  signature : ECDSASignature,
) -> Result[Bool, String] {
  if message_hash.length() != 32 {
    return Err("Message hash must be 32 bytes")
  }

  let q = match parse_public_key(public_key) {
    Err(e) => return Err(e)
    Ok(p) => p
  }

  let r = sc_from_bytes(signature.r)
  let s = sc_from_bytes(signature.s)

  if !sc_is_valid(r) || !sc_is_valid(s) {
    return Ok(false)
  }

  // z = hash as scalar
  let z_bytes : Array[UInt] = []
  for i in 0.. Result[Bool, String] {
  let hash = @sha2.Sha256::digest(message)
  ecdsa_verify(public_key, hash, signature)
}

/// Bytes API wrappers
pub fn ecdsa_keygen_bytes(private_key : Bytes) -> Result[ECDSAKeyPair, String] {
  ecdsa_keygen(bytes_to_uint_array(private_key))
}

pub fn ecdsa_sign_bytes(
  private_key : Bytes,
  message : Bytes,
) -> Result[ECDSASignature, String] {
  ecdsa_sign_message(bytes_to_uint_array(private_key), bytes_to_uint_array(message))
}

pub fn ecdsa_verify_bytes(
  public_key : Bytes,
  message : Bytes,
  signature : ECDSASignature,
) -> Result[Bool, String] {
  ecdsa_verify_message(bytes_to_uint_array(public_key), bytes_to_uint_array(message), signature)
}