"""Path helpers for the final-report markdown/data.json pair and its sidecars."""
from __future__ import annotations

from pathlib import Path


DATA_JSON_SUFFIX = ".data.json"
MARKDOWN_SUFFIX = ".md"
TRANSLATION_SOURCE_SUFFIX = ".translation-source.json"


def _stem(data_path: Path) -> str:
    name = data_path.name
    return name[: -len(DATA_JSON_SUFFIX)] if name.endswith(DATA_JSON_SUFFIX) else data_path.stem


def require_approved_plan_record(path: Path) -> Path:
    """`--approved-plan` accepts the report record only.

    A full reading copy (`.md`) is rejected with the sibling record path.
    Schema-v1 plans have no record and cannot enter this gate.
    """
    resolved = Path(path)
    if is_full_reading_copy_path(resolved):
        suggested = final_report_data_path(resolved)
        raise ValueError(
            f"--approved-plan must be the report record (.data.json), not the "
            f"full reading copy: {path}\n"
            "  schema-v1 plans have no record and cannot be used here.\n"
            f"  for a schema-v2 plan use: {suggested}"
        )
    if not is_report_record_path(resolved):
        raise ValueError(
            f"--approved-plan must be a report record ending in .data.json: {path}"
        )
    if not resolved.is_file():
        raise ValueError(f"approved plan record not found: {path}")
    return resolved


def is_report_record_path(path: Path) -> bool:
    return path.name.endswith(DATA_JSON_SUFFIX)


def is_full_reading_copy_path(path: Path) -> bool:
    return path.name.endswith(MARKDOWN_SUFFIX)


def final_report_data_path(report_path: Path) -> Path:
    """Return the report record path for a final-report pair.

    Already a `.data.json` path is returned unchanged.
    """
    name = report_path.name
    if name.endswith(DATA_JSON_SUFFIX):
        return report_path
    if name.endswith(MARKDOWN_SUFFIX):
        return report_path.with_name(name[: -len(MARKDOWN_SUFFIX)] + DATA_JSON_SUFFIX)
    return report_path.with_suffix(DATA_JSON_SUFFIX)


def final_report_markdown_path(data_path: Path) -> Path:
    """Return the markdown sibling for a final-report data.json path."""
    name = data_path.name
    if name.endswith(DATA_JSON_SUFFIX):
        return data_path.with_name(name[: -len(DATA_JSON_SUFFIX)] + MARKDOWN_SUFFIX)
    return data_path.with_suffix(MARKDOWN_SUFFIX)


def report_record_rel_from_legacy_pointer(relative: str) -> str:
    """Turn a stored pointer into a report-record relative path.

    New rows store the record. Rows written before that stored the full
    reading copy (`.md`); the record is the sibling `.data.json`.
    """
    relative = str(relative or "")
    if not relative:
        return ""
    path = Path(relative)
    if is_report_record_path(path):
        return relative
    return str(final_report_data_path(path))


def index_report_record_rel(row: dict) -> str:
    """Report-record pointer from a run-index row.

    New rows use `finalReportRecordRel`. Older rows used `finalReportRel`
    for the full reading copy.
    """
    current = str(row.get("finalReportRecordRel") or "")
    if current:
        return current
    return report_record_rel_from_legacy_pointer(str(row.get("finalReportRel") or ""))


def timeline_report_record_rel(run: dict) -> str:
    """Report-record pointer from a timeline / recap run entry.

    New entries use `reportRecordPath`. Older entries used `reportPath`
    for the full reading copy.
    """
    current = str(run.get("reportRecordPath") or "")
    if current:
        return current
    return report_record_rel_from_legacy_pointer(str(run.get("reportPath") or ""))


def translation_source_path(data_path: Path) -> Path:
    """Return the translator's work list for a final-report data.json path."""
    return data_path.with_name(_stem(data_path) + TRANSLATION_SOURCE_SUFFIX)


def translation_sidecar_path(data_path: Path, lang: str) -> Path:
    """Return the filled translation sidecar the HTML renderer overlays.

    One file per language beside the report it translates, so the renderer
    finds it from the data.json alone and a run for another language does not
    overwrite it.
    """
    return data_path.with_name(f"{_stem(data_path)}.i18n.{lang}.json")
