# grantflow/swarm/nodes/architect.py

from __future__ import annotations

from typing import Any, Dict

from grantflow.swarm.citations import append_citations
from grantflow.swarm.nodes.architect_generation import generate_toc_under_contract
from grantflow.swarm.nodes.architect_retrieval import retrieve_architect_evidence
from grantflow.swarm.state_contract import (
    normalize_state_contract,
    set_state_donor_strategy,
    state_donor_id,
    state_donor_strategy,
    state_input_context,
    state_iteration,
    state_rag_namespace,
    state_revision_hint,
)
from grantflow.swarm.versioning import append_draft_version


def draft_toc(state: Dict[str, Any]) -> Dict[str, Any]:
    """
    Создаёт черновик Theory of Change.
    """
    normalize_state_contract(state)
    strategy = state_donor_strategy(state)
    iteration = state_iteration(state)
    donor_id = state_donor_id(state)
    input_context = state_input_context(state)

    if not strategy:
        state.setdefault("errors", []).append("Architect cannot run without donor_strategy")
        return state

    revision_hint = state_revision_hint(state)

    namespace = state_rag_namespace(state, default=strategy.get_rag_collection())
    retrieval_summary, retrieval_hits = retrieve_architect_evidence(state, namespace)

    try:
        toc, validation, generation_meta, claim_citations = generate_toc_under_contract(
            state=state,
            strategy=strategy,
            evidence_hits=retrieval_hits,
        )
    except Exception as exc:
        state.setdefault("errors", []).append(f"Architect ToC generation failed: {exc}")
        state["toc_validation"] = {
            "valid": False,
            "schema_name": getattr(getattr(strategy, "get_toc_schema", lambda: object)(), "__name__", "TOCSchema"),
            "error_count": 1,
            "errors": [str(exc)],
        }
        # Keep legacy-shaped fallback to avoid breaking downstream nodes in hard-failure scenarios.
        toc = {
            "brief": f"ToC draft for {donor_id} (pass {iteration + 1})",
            "project": input_context.get("project", "TBD project"),
            "country": input_context.get("country", "TBD"),
            "objectives": [
                {
                    "title": "Objective 1",
                    "description": f"Deliver results aligned to {donor_id} guidance.",
                    "citation": namespace,
                }
            ],
            "revision_basis": revision_hint,
        }
        generation_meta = {
            "engine": "fallback:legacy_template",
            "llm_used": False,
            "retrieval_used": bool(retrieval_hits),
            "llm_fallback_reason": str(exc),
        }
        claim_citations = [
            {
                "stage": "architect",
                "citation_type": "strategy_namespace",
                "namespace": namespace,
                "label": f"Based on {namespace}",
                "used_for": "toc_draft",
                "statement_path": "toc",
            }
        ]
        validation = state["toc_validation"]

    set_state_donor_strategy(state, strategy)
    state["toc"] = toc
    state["toc_validation"] = validation
    state["architect_retrieval"] = retrieval_summary
    state["toc_generation_meta"] = generation_meta
    state["toc_draft"] = {
        "toc": toc,
        "proposal_mode": input_context.get("proposal_mode"),
        "rfq_profile": input_context.get("rfq_profile"),
        "citation": f"Based on {namespace}",
        "generation_meta": generation_meta,
        "validation": validation,
        "architect_retrieval": retrieval_summary,
    }
    append_draft_version(
        state,
        section="toc",
        content=state["toc_draft"],
        node="architect",
        iteration=iteration + 1,
    )
    append_citations(state, claim_citations)
    return state
