import sys, os
import unittest
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))

from transpiler.transformer import transform
from transpiler.generator import generate
from transpiler.flags import CompilerFlags
import ast as pyast

class TestEvilSuite(unittest.TestCase):
    def _gen(self, source: str) -> str:
        tree = pyast.parse(source)
        res = transform(tree)
        flags = CompilerFlags(no_runtime=True, fast=True)
        result = generate(res, flags=flags)
        return result.code
    def test_nested_break_continue(self):
        source = """
x = 0
for i in range(10):
    if i % 2 == 0:
        continue
    for j in range(5):
        if j == 3:
            break
        if i == 5 and j == 2:
            x += 100
            break
        x += 1
    if x > 200:
        break
print(x)
"""
        code = self._gen(source)
        # Verify loops and breaks are generated properly
        self.assertIn("while", code)
        self.assertIn("break", code)
        self.assertIn("continue", code)
        # 1 break for j == 3, 1 break for i == 5, 1 break for x > 200
        # Wait, if x > 200 is outside the inner loop, it's 3 breaks.
        # But wait! If `break` is heavily optimized, maybe the number changes?
        # Let's just verify it compiles and contains multiple breaks.
        if code.count("break") < 2:
            print("BREAK CODE:\n", code)
        self.assertTrue(code.count("break") >= 2)
        self.assertTrue(code.count("continue") >= 1)

    def test_short_circuit_and_or_side_effects(self):
        source = """
y = [0]
def mutate(x):
    y[0] += x
    return x > 0

a = mutate(10) and mutate(-5) and mutate(20)
b = mutate(-10) or mutate(5) or mutate(-20)
"""
        code = self._gen(source)
        if code.count("mutate") != 7:
            print("SHORT CIRCUIT CODE:\n", code)
        self.assertIn(" and ", code)
        self.assertIn(" or ", code)
        self.assertEqual(code.count("mutate"), 7)
        
    def test_expression_evaluation_order(self):
        source = """
def a():
    print("A")
    return 1

def b():
    print("B")
    return 2

def c(x, y):
    return x + y

res = c(a(), b())
"""
        code = self._gen(source)
        # Remove spaces and newlines for robust assertion
        normalized_code = code.replace(" ", "").replace("\\n", "")
        self.assertIn("c(a(),b())", normalized_code)

if __name__ == "__main__":
    unittest.main()
