from __future__ import annotations

"""Simple, model-agnostic basic QA recipe.

This recipe is intentionally deterministic and does *not* call any external
LLM. It is designed to:

- Provide a basic QA-style dataset from a :class:`DocumentGraph`.
- Establish the JSONL schema and integration points for more advanced,
  LLM-backed implementations.

Each paragraph node yields one QA pair of the form::

    Q: "What is the main idea of the following text?" + snippet
    A: full paragraph text (or first sentence in the future).
"""

from pathlib import Path
import json

from ..core.models import DatasetRecipe, DocumentGraph, NodeType
from ..llm import LLMClient, build_llm_from_recipe_params


def _ensure_recipe(recipe: DatasetRecipe | None) -> DatasetRecipe:
    if recipe is not None:
        return recipe
    return DatasetRecipe(
        name="basic_qa",
        description="Default basic QA recipe (one QA per paragraph).",
        input_query="",
        prompt_template="",
        output_schema={"question": "str", "answer": "str"},
    )


def run_basic_qa(
    recipe: DatasetRecipe | None,
    graph: DocumentGraph,
    base_dir: str | Path,
    document_id: str,
) -> Path:
    """Generate a simple QA dataset from paragraph nodes.

    Output format: JSONL with fields ``question``, ``answer`` and ``metadata``.
    """

    recipe = _ensure_recipe(recipe)

    llm: LLMClient | None = build_llm_from_recipe_params(getattr(recipe, "params", None))

    base = Path(base_dir)
    ds_dir = base / "datasets" / recipe.name
    ds_dir.mkdir(parents=True, exist_ok=True)
    out_path = ds_dir / f"{document_id}.jsonl"

    with out_path.open("w", encoding="utf-8") as f:
        for node in graph.nodes:
            if node.node_type is not NodeType.PARAGRAPH:
                continue

            text = (node.label or "").strip()
            if not text:
                continue

            snippet = text
            if len(snippet) > 200:
                snippet = snippet[:197] + "..."

            question = (
                "What is the main idea of the following text?\n\n" + snippet
            )

            if llm is None:
                answer = text
            else:
                # Let the LLM produce a potentially richer answer based on the
                # paragraph text. With the DummyLLMClient used in tests, this is
                # fully deterministic.
                answer = llm.generate(text)

            record = {
                "document_id": document_id,
                "node_id": node.id,
                "question": question,
                "answer": answer,
                "metadata": {
                    **(graph.metadata or {}),
                    **(node.metadata or {}),
                },
            }
            f.write(json.dumps(record, ensure_ascii=False) + "\n")

    return out_path

