"""Analysis material body + related-tasks builders.

bash `build_review_material`, `resolve_related_tasks_json`,
`build_related_tasks_bullets`, `build_related_tasks_inline` 의 python 구현.
brief 본문과 directive 를 합쳐 lead 가 읽을 `analysis-material.md` 본문을
만들고, 이미 manifest 에 기록된 related-tasks 와 새 입력을 merge 한다.
"""
from __future__ import annotations

import json
from pathlib import Path
from typing import Optional
from okstra_project import list_project_tasks

from .json_boundary import JsonBoundaryError, load_owned_object


def build_analysis_material(brief_path: Path, directive: str = "") -> str:
    """`analysis-material.md` 본문 문자열을 돌려준다."""
    parts = ["# OKSTRA Analysis Material", "", "## Task Brief", ""]
    parts.append(Path(brief_path).read_text(encoding="utf-8").rstrip())
    if directive:
        parts.append("")
        parts.append("## Directive")
        parts.append("")
        parts.append(
            "> Free-form directive supplied via `--directive`. Treat as a hard hint that may override default heuristics in lead, workers, and downstream skills (e.g. okstra-schedule-gen's Gantt skip gate)."
        )
        parts.append("")
        parts.append(directive)
    return "\n".join(parts).rstrip() + "\n"


def resolve_related_tasks(
    *, task_manifest_path: Optional[Path], raw_related: str
) -> list[str]:
    """기존 manifest 의 relatedTasks + 새 CSV 입력을 dedupe-merge."""
    existing: list[str] = []
    if task_manifest_path and Path(task_manifest_path).exists():
        try:
            manifest = load_owned_object(
                Path(task_manifest_path), artifact="task manifest"
            )
            existing = manifest.get("relatedTasks") or []
            if not isinstance(existing, list):
                existing = []
        except JsonBoundaryError:
            existing = []
    provided = [v.strip() for v in (raw_related or "").split(",") if v.strip()]
    seen: set[str] = set()
    out: list[str] = []
    for v in [*existing, *provided]:
        if not v or v in seen:
            continue
        seen.add(v)
        out.append(v)
    return out


def related_tasks_bullets(items: list[str]) -> str:
    if not items:
        return "- None recorded"
    return "\n".join(f"- `{v}`" for v in items)


def related_tasks_inline(items: list[str]) -> str:
    return ", ".join(items) if items else "None"


def direct_work_context(project_root: Path, task_key: str, related: list[str]) -> str:
    """자기 작업과 다른 그룹의 명시적 관련 작업 결과를 준비 입력에 싣는다."""
    own_group = task_key.split(":")[1].casefold()
    wanted = {value.casefold() for value in related}
    blocks = []
    for task in list_project_tasks(project_root):
        key = task["taskKey"]
        is_own = key.casefold() == task_key.casefold()
        is_related = key.casefold() in wanted or str(task.get("taskId", "")).casefold() in wanted
        if not is_own and (not is_related or str(task.get("taskGroup", "")).casefold() == own_group):
            continue
        record_path = task.get("latestWorkRecordPath")
        if not record_path:
            continue
        record_file = project_root / record_path
        record_file.resolve().relative_to((project_root / ".okstra").resolve())
        record = load_owned_object(record_file, artifact="direct work record")
        blocks.extend([
            f"### {key}", f"- Current work status: {task.get('workStatus', '')}",
            "- Source: direct work; no cross-verification performed for this record.",
            f"- Summary: {' '.join(record['summary'].split())[:400]}",
            f"- Record: `{record_path}`", "",
        ])
    if not blocks:
        return ""
    return "\n".join(["## Direct Work Context", "", *blocks])
