"""This helper supports submitting completed notebooks for credit by extracting student responses and sending them to a remote grading service."""

# AUTOGENERATED! DO NOT EDIT! File to edit: ../../nbs/helpers/02_submit.ipynb.

# %% auto 0
__all__ = ['collect_answers', 'parse_answers', 'submit_answers', 'review_answers']

# %% ../../nbs/helpers/02_submit.ipynb 4
import os
import httpx
import nbformat
from pathlib import Path
import inspect
import re
import json

# %% ../../nbs/helpers/02_submit.ipynb 5
def _can_use_dialoghelper():
    try:
        from dialoghelper import find_msgs
        return True
    except Exception:
        return False

# %% ../../nbs/helpers/02_submit.ipynb 6
def _collect_answers_from_notebook(path=None):
    """
    Collect qN_answer assignments by parsing a notebook file directly.
    Works in local Jupyter.
    """
    if path is None:
        # Infer the current notebook path (best-effort)
        frame = inspect.currentframe()
        while frame:
            fname = frame.f_globals.get("__file__")
            if fname and fname.endswith(".ipynb"):
                path = fname
                break
            frame = frame.f_back

        if path is None:
            raise RuntimeError(
                "Could not infer notebook path. "
                "Pass path= explicitly when running locally."
            )

    nb = nbformat.read(Path(path), as_version=4)

    results = []
    pat = re.compile(r'^q\d+_answer\s*=', re.MULTILINE)

    for cell in nb.cells:
        if cell.cell_type == "code":
            for line in cell.source.splitlines():
                if pat.match(line.strip()):
                    results.append(("code", line.strip()))

    return results


# %% ../../nbs/helpers/02_submit.ipynb 7
def collect_answers(show=True, *, dname=None, path=None):
    """
    Collect student answers from a notebook.

    - Uses dialoghelper when available (Solveit / Deepnote)
    - Falls back to parsing the notebook file locally (JupyterLab)

    Parameters
    ----------
    show : bool
        Print extracted answers
    dname : str, optional
        Dialog name (Solveit only)
    path : str or Path, optional
        Notebook path (required for reliable local execution)

    Returns
    -------
    list[tuple]
    """
    # Attempt dialoghelper first
    try:
        from dialoghelper import find_msgs

        msgs = find_msgs(
            re_pattern=r'^q\d+_answer\s*=',
            msg_type='code',
            dname=dname
        )
        results = [('code', msg['content'].strip()) for msg in msgs]

    except Exception:
        # Fallback: local notebook parsing
        results = _collect_answers_from_notebook(path=path)

    if show:
        print("=== Student Responses ===\n")
        for _, answer in results:
            print(answer)

    return results

# %% ../../nbs/helpers/02_submit.ipynb 8
def parse_answers(raw):
    """
    Parse extracted answer code into a dictionary.

    Parameters
    ----------
    raw : list of tuple
        Output from `collect_answers`, containing raw code strings.

    Returns
    -------
    dict
        Mapping from answer variable name (e.g. 'q1_answer') to its value.
    """
    result = {}
    for typ, content in raw:
        if typ == 'code':
            # Parse "q1_answer = "A"" format
            key, val = content.split(' = ', 1)
            result[key] = eval(val)
    return result

# %% ../../nbs/helpers/02_submit.ipynb 9
def submit_answers(
    student_id, 
    *, 
    path,
    raw_answers=None,
    dname=None, 
    url="https://nbsubmit-production.up.railway.app", 
    api_key=None,
    verbose=True,
):
    """
    Submit parsed student answers to the grading service.

    Parameters
    ----------
    student_id : str
        Identifier for the student submitting the notebook.
    raw_answers : list of tuple, optional
        Raw extracted answers. If omitted, answers are collected automatically.
    url : str
        Base URL of the submission service.
    api_key : str, optional
        API key for authentication. If not provided, read from environment.

    Returns
    -------
    dict
        Parsed JSON response from the submission server.
    """
    if not student_id.strip():
        raise ValueError("student_id cannot be empty")
    if raw_answers is None:
        raw_answers = collect_answers(show=False, dname=dname, path=path)
    answers = parse_answers(raw_answers)

    payload = {
        "student_id": student_id,
        "answers": answers,
    }

    if verbose:
        print("\n📤 YOUR SUBMISSION")
        print("=" * 60)
        print(json.dumps(payload, indent=2))
        print("=" * 60)
        
    headers = {"x-api-key": api_key or os.environ.get("SUBMIT_API_KEY")}
    key = api_key or os.environ.get("SUBMIT_API_KEY")
    if not key:
        raise RuntimeError(
            "Missing SUBMIT_API_KEY. Set it in your environment or .env file."
        )
    headers = {"x-api-key": key}
    response = httpx.post(f"{url}/submit", json={"student_id": student_id, "answers": answers}, headers=headers)
    return response.json()

# %% ../../nbs/helpers/02_submit.ipynb 11
def review_answers(*, path, dname=None, show=True):
    """
    Review extracted student answers WITHOUT submitting.

    Parameters
    ----------
    path : str or Path
        Path to the notebook being reviewed.
    dname : str, optional
        Dialog name (Solveit / Deepnote).
    show : bool
        Print formatted output.

    Returns
    -------
    dict
        Parsed answers ready for submission.
    """
    raw = collect_answers(show=False, dname=dname, path=path)
    answers = parse_answers(raw)

    if show:
        print("\n📝 REVIEW: Answers detected in this notebook")
        print("=" * 60)
        for k, v in answers.items():
            print(f"{k}: {v!r}")
        print("=" * 60)
        print("⚠️  Nothing has been submitted.")

    return answers

