// AVM ISA v1 — Scala Test Harness
import silversight.avm.AVM._
import silversight.avm.AVM

object TestAVM {
  val QS = Q16Scale

  def check(cond: Boolean, msg: String): Unit = {
    if (cond) println(s"  ✅ $msg")
    else println(s"  ❌ $msg")
  }

  def test_basic_add(): Unit = {
    val prog = Vector(PushQ16(5 * QS), PushQ16(3 * QS), Primitive(AddSatQ16), Halt)
    val s = run(initState(), prog, 100).get
    check(s.stack.head.i == 8 * QS, "basic_add: 5 + 3 = 8")
  }

  def test_div_q16(): Unit = {
    val prog = Vector(PushQ16(3 * QS), PushQ16(5 * QS), Primitive(DivSatQ16), Halt)
    val s = run(initState(), prog, 100).get
    val exp = (3 * QS) / 5
    check(s.stack.head.i == exp, "div_q16: 3/5 = 0.6")
  }

  def test_saturation(): Unit = {
    val prog = Vector(PushQ16(AVMClampMax - 1), PushQ16(2), Primitive(AddSatQ16), Halt)
    val s = run(initState(), prog, 100).get
    check(s.stack.head.i == AVMClampMax, "saturation: max-1+2 = max")
  }

  def test_v6_lt(): Unit = {
    val cases = Seq((-5*QS, -3*QS, true), (-3*QS, -5*QS, false),
      (5*QS, 3*QS, false), (3*QS, 5*QS, true), (-1*QS, 2*QS, true))
    cases.foreach { case (a, b, exp) =>
      val prog = Vector(PushQ16(a), PushQ16(b), Primitive(LtQ16), Halt)
      val s = run(initState(), prog, 100).get
      check(s.stack.head.b == exp, s"v6_lt($a,$b) = $exp")
    }
  }

  def test_type_mismatch(): Unit = {
    val prog = Vector(PushBool(true), PushQ16(QS), Primitive(AddSatQ16))
    val s = run(initState(), prog, 100)
    check(s.isEmpty, "type_mismatch: rejected")
  }

  def test_div_by_zero(): Unit = {
    val prog = Vector(PushQ16(QS), PushQ16(0), Primitive(DivSatQ16))
    val s = run(initState(), prog, 100)
    check(s.isEmpty, "div_by_zero: rejected")
  }

  def test_stack_overflow(): Unit = {
    val prog = Vector.fill(AVMMaxStack + 1)(PushQ16(0: Int))
    val s = run(initState(), prog, 10000)
    check(s.isEmpty, "stack_overflow: rejected")
  }

  def test_control_flow(): Unit = {
    val prog = Vector(PushBool(true), JumpIf(4), PushQ16(0), Halt, PushQ16(QS), Halt)
    val s = run(initState(), prog, 100).get
    check(s.stack.head.i == QS, "control_flow: jump_if true")
  }

  def test_locals(): Unit = {
    val prog = Vector(PushQ16(42 * QS), Store(0), Load(0), Halt)
    val s = run(initState(1), prog, 100).get
    check(s.stack.head.i == 42 * QS, "locals: store+load")
  }

  def main(args: Array[String]): Unit = {
    println("AVM Scala Port — Test Harness")
    println("==============================")
    test_basic_add(); test_div_q16(); test_saturation(); test_v6_lt()
    test_type_mismatch(); test_div_by_zero(); test_stack_overflow()
    test_control_flow(); test_locals()
    println("\nAll Scala tests passed.")
  }
}
