import json
import traceback
from pathlib import Path

from .runtime_paths import build_paths


def execute_notebook(
    start_at: int | None = None,
    stop_at: int | None = None,
    namespace: dict | None = None,
) -> dict:
    paths = build_paths()
    paths.ensure_outputs()

    nb_data = json.loads(paths.notebook.read_text(encoding="utf-8"))
    code_cells = [c for c in nb_data["cells"] if c["cell_type"] == "code"]
    if not code_cells:
        return {"status": "skipped", "reason": "no code cells found"}

    ns = (namespace or {}).copy()
    ns.update(paths.as_injection())
    ns["RANDOM_STATE"] = 42

    start = max((start_at or 1) - 1, 0)
    stop = stop_at if stop_at is not None else len(code_cells)
    cells_to_run = code_cells[start:stop]

    results = []
    for i, cell in enumerate(cells_to_run, start=start + 1):
        src = "".join(cell["source"])
        tag = f"cell_{i}"
        try:
            exec(compile(src, tag, "exec"), ns)
            results.append({"cell": i, "status": "ok"})
        except Exception as exc:
            results.append({"cell": i, "status": "error", "error": str(exc)})
            traceback.print_exc()
            print(f"Stopping at cell {i} due to error.")
            break

    results_summary = {
        "status": "completed",
        "total": len(cells_to_run),
        "cells": results,
        "outputs": {
            "data_dir": str(paths.data_dir),
            "output_dir": str(paths.output_dir),
        },
    }
    return results_summary


if __name__ == "__main__":
    execute_notebook()