import subprocess
import csv
import io
import os

HARNESS_PATH = os.path.join(
    os.path.dirname(__file__), "..", "harness", "ml_kem_harness"
)

class LiboqsTarget:
    """
    Production target: liboqs ML-KEM-768 (C implementation).
    Calls the C harness binary and reads timing via CSV.
    """

    def __init__(self, num_traces: int = 100000):
        self.num_traces = num_traces
        self._verify_harness()

    def _verify_harness(self):
        path = os.path.abspath(HARNESS_PATH)
        if not os.path.exists(path):
            raise FileNotFoundError(
                f"C harness not found at {path}\n"
                f"Build it first:\n"
                f"  cd harness && gcc -O2 -o ml_kem_harness ml_kem_harness.c -loqs -lssl -lcrypto"
            )
        print(f"  [*] liboqs harness found at {path}")

    def run_decaps(self) -> tuple[list, list]:
        return self._run_harness("decaps")

    def run_encaps(self) -> tuple[list, list]:
        return self._run_harness("encaps")

    def _run_harness(self, mode: str) -> tuple[list, list]:
        path = os.path.abspath(HARNESS_PATH)
        print(f"  [*] Running C harness: {mode}, {self.num_traces} traces...")

        result = subprocess.run(
            [path, str(self.num_traces), mode],
            capture_output=True,
            text=True,
            timeout=600
        )

        if result.returncode != 0:
            raise RuntimeError(f"C harness failed:\n{result.stderr}")

        if result.stderr:
            for line in result.stderr.strip().splitlines():
                print(f"    {line}")

        fixed_times  = []
        random_times = []

        reader = csv.DictReader(io.StringIO(result.stdout))
        for row in reader:
            fixed_times.append(int(row["fixed_ns"]))
            random_times.append(int(row["random_ns"]))

        print(f"  [*] Parsed {len(fixed_times)} trace pairs.")
        return fixed_times, random_times
