"""Fluxo linear da revisão: navegação anterior/próxima e status no menu."""

from __future__ import annotations

from dataclasses import dataclass

from django.urls import reverse

from rsl.services.workflow import (
    get_conducting_steps,
    get_planning_steps,
    review_has_articles,
    review_has_sources,
)


@dataclass(frozen=True)
class FlowStepDef:
    endpoint: str
    label: str
    icon: str
    anchor: str = ""
    phase: str = ""  # planning | conducting | reporting | overview


# Ordem sugerida para conduzir a revisão (UX linear)
REVIEW_FLOW: list[FlowStepDef] = [
    FlowStepDef("reviews.detail", "Painel", "tachometer-alt", phase="overview"),
    FlowStepDef("planning.protocol", "Protocolo", "file-alt", anchor="bases", phase="planning"),
    FlowStepDef("planning.quality", "Checklist de qualidade", "check-double", phase="planning"),
    FlowStepDef("planning.extraction", "Formulário de extração", "table", phase="planning"),
    FlowStepDef("conducting.import_studies", "Importar estudos", "file-import", phase="conducting"),
    FlowStepDef("conducting.selection", "Seleção de estudos", "filter", phase="conducting"),
    FlowStepDef(
        "conducting.quality_assessment",
        "Avaliação de qualidade",
        "star",
        phase="conducting",
    ),
    FlowStepDef("conducting.data_extraction", "Extração de dados", "edit", phase="conducting"),
    FlowStepDef("conducting.analysis", "Análise de dados", "chart-bar", phase="conducting"),
    FlowStepDef("reporting.synthesis", "Síntese da RSL", "file-alt", phase="reporting"),
    FlowStepDef("reporting.index", "Exportar relatório", "download", phase="reporting"),
]

# Endpoints que contam como a mesma etapa no fluxo
ENDPOINT_ALIASES: dict[str, str] = {
    "planning.index": "planning.protocol",
    "conducting.search": "planning.protocol",
    "conducting.index": "conducting.import_studies",
    "reviews.settings": "reviews.detail",
}


def _normalize_endpoint(endpoint: str | None) -> str:
    if not endpoint:
        return ""
    return ENDPOINT_ALIASES.get(endpoint, endpoint)


def _step_url(review_id: int, step: FlowStepDef) -> str:
    name = step.endpoint.replace(".", ":", 1)
    url = reverse(name, kwargs={"review_id": review_id})
    if step.anchor:
        url += f"#{step.anchor}"
    return url





def _is_blocked(review, step: FlowStepDef) -> tuple[bool, str]:
    if step.endpoint == "conducting.import_studies" and not review_has_sources(review):
        return True, "Selecione as bases no Protocolo."
    if step.endpoint == "conducting.selection" and not review_has_articles(review):
        return True, "Importe estudos antes da seleção."
    if step.endpoint == "conducting.quality_assessment":
        from rsl.services.workflow import review_has_accepted

        if not review_has_accepted(review):
            return True, "Aceite artigos na seleção primeiro."
        if not review.quality_questions.exists():
            return True, "Defina o checklist no Planejamento."
    if step.endpoint == "conducting.data_extraction":
        from rsl.services.workflow import review_has_extraction_form

        if not review_has_extraction_form(review):
            return True, "Crie o formulário de extração no Planejamento."
    if step.endpoint == "conducting.analysis" and not review_has_articles(review):
        return True, "Importe artigos para analisar."
    return False, ""


def _step_done(review, step: FlowStepDef, planning_by_key: dict, conducting_by_key: dict) -> bool:
    key_map = {
        "reviews.detail": None,
        "planning.protocol": "sources",
        "planning.quality": "quality_design",
        "planning.extraction": "extraction_design",
        "conducting.import_studies": "import",
        "conducting.selection": "selection",
        "conducting.quality_assessment": "qa",
        "conducting.data_extraction": "extraction",
        "conducting.analysis": "analysis",
        "reporting.synthesis": None,
        "reporting.index": None,
    }
    key = key_map.get(step.endpoint)
    if key is None:
        if step.endpoint == "reviews.detail":
            return True
        if step.endpoint in ("reporting.index", "reporting.synthesis"):
            return review_has_articles(review)
        return False
    if key in planning_by_key:
        return planning_by_key[key].done
    if key in conducting_by_key:
        return conducting_by_key[key].done
    return False


def build_flow_navigation(review, current_endpoint: str | None) -> dict:
    """Monta barra de progresso e links anterior/próximo."""
    current = _normalize_endpoint(current_endpoint)
    planning = {s.key: s for s in get_planning_steps(review)}
    conducting = {s.key: s for s in get_conducting_steps(review)}

    steps = []
    current_index = 0
    for i, defn in enumerate(REVIEW_FLOW):
        blocked, block_reason = _is_blocked(review, defn)
        done = _step_done(review, defn, planning, conducting)
        ep = defn.endpoint
        if ep == current:
            current_index = i
        steps.append(
            {
                "endpoint": ep,
                "label": defn.label,
                "icon": defn.icon,
                "phase": defn.phase,
                "url": _step_url(review.id, defn),
                "done": done,
                "blocked": blocked,
                "block_reason": block_reason,
                "active": ep == current,
            }
        )

    prev_step = next_step = None
    if current_index > 0:
        p = steps[current_index - 1]
        prev_step = {"url": p["url"], "label": p["label"]}
    if current_index < len(steps) - 1:
        n = steps[current_index + 1]
        next_step = {
            "url": n["url"],
            "label": n["label"],
            "blocked": n["blocked"],
            "block_reason": n["block_reason"],
        }

    return {
        "steps": steps,
        "current_index": current_index,
        "current_label": steps[current_index]["label"] if steps else "",
        "total": len(steps),
        "prev": prev_step,
        "next": next_step,
        "progress_pct": int(100 * (current_index + 1) / len(steps)) if steps else 0,
    }


def sidebar_step_status(review) -> dict[str, dict]:
    """Status por endpoint para ícones no menu lateral."""
    nav = build_flow_navigation(review, None)
    return {s["endpoint"]: {"done": s["done"], "blocked": s["blocked"]} for s in nav["steps"]}
