"""Single source of truth for the okstra-relative directory name.

okstra 가 한 프로젝트 안에 만드는 모든 산출물은 `<PROJECT_ROOT>/.okstra/`
한 디렉토리 아래 모인다. 이 모듈은 그 디렉토리 이름과 자주 쓰이는 하위 path 조합을
한 곳에서 export 한다. 호출자는 절대 path 문자열을 직접 만들지 말고 여기의 상수 /
헬퍼를 사용해야 한다.

DRY 위반의 비용: 이전에는 동일 path 문자열이 50+ Python·Shell·markdown 파일에
중복으로 박혀 있었고, 디렉토리 이름을 바꾸려면 60+ 파일을 동시에 수정해야 했다.
이 모듈은 그 비용을 한 줄 수정으로 줄인다.

의존성 0 (stdlib only). `paths.py` 와 `state.py` 양쪽에서 import 되므로 순환 위험을
피하기 위해 다른 okstra 모듈을 import 하지 않는다.
"""
from __future__ import annotations

import os
import sys
import tempfile
from pathlib import Path

OKSTRA_DIR_NAME = ".okstra"
"""Project-relative directory name where okstra stores all per-project state.

CLI / docs / message 문자열도 모두 이 값과 일치해야 한다. 값 자체를 import 해 쓰는
대신 path 합성에는 `OKSTRA_RELATIVE` / `okstra_root()` 등을 권장.
"""

LEGACY_OKSTRA_DIR_NAME = ".project-docs/okstra"
"""Pre-v0.37 layout. ``okstra migrate`` reads this to find unmigrated projects.

코드 path 빌드에는 절대 사용 금지 — `OKSTRA_DIR_NAME` / `OKSTRA_RELATIVE` 만.
오로지 migration 탐지/안내 메시지 용도.
"""

OKSTRA_RELATIVE = Path(OKSTRA_DIR_NAME)
LEGACY_OKSTRA_RELATIVE = Path(LEGACY_OKSTRA_DIR_NAME)
PROJECT_JSON_RELATIVE = OKSTRA_RELATIVE / "project.json"
TASKS_RELATIVE = OKSTRA_RELATIVE / "tasks"

TASK_MANIFEST_FILENAME = "task-manifest.json"
"""task root 안의 lifecycle manifest 파일명.

`okstra_ctl.paths.task_manifest_path` 와 `okstra_project.state.read_task_manifest`
양쪽이 이 상수를 쓴다 — paths 가 state 를 import 하므로 역방향 import 는 순환이고,
두 계층이 공유할 수 있는 자리는 여기뿐이다."""
DISCOVERY_RELATIVE = OKSTRA_RELATIVE / "discovery"
TASK_CATALOG_RELATIVE = DISCOVERY_RELATIVE / "task-catalog.json"
LATEST_TASK_RELATIVE = DISCOVERY_RELATIVE / "latest-task.json"


def _is_stale_tmp_home(path: str) -> bool:
    """삭제된 pytest 격리 OKSTRA_HOME 누수 판별. tests/conftest.py 가 격리 홈을
    ``<tmp_path>/.okstra-isolated``(시스템 임시 하위)로 만드는데, 그 디렉터리가
    사라진 채 env 만 남은 경우만 폴백 대상이다. 실제/커스텀 홈이나 곧 생성될
    임시 홈(``.okstra`` 등)은 이름이 달라 걸리지 않는다(테스트 오폴백 방지)."""
    if Path(path).name != ".okstra-isolated":
        return False
    roots = [
        tempfile.gettempdir(),
        "/tmp", "/private/tmp", "/var/folders", "/private/var/folders",
    ]
    return any(path == r or path.startswith(r.rstrip("/") + "/")
               for r in roots if r)


def okstra_home() -> Path:
    """`~/.okstra` 절대 path. 테스트/설치 환경에서 `OKSTRA_HOME` env 로 override.

    OKSTRA_HOME 이 존재하지 않는 시스템 임시 경로(삭제된 pytest 격리 홈 등
    누수된 값)를 가리키면 stderr 경고 후 기본 `~/.okstra` 로 폴백한다."""
    override = os.environ.get("OKSTRA_HOME", "").strip()
    if not override:
        return Path.home() / ".okstra"
    home = Path(override).expanduser()
    if not home.exists() and _is_stale_tmp_home(str(home)):
        sys.stderr.write(
            f"⚠ OKSTRA_HOME={override} 가 존재하지 않는 임시 경로입니다 "
            "(누수된 테스트 격리 값으로 보임) → ~/.okstra 로 폴백합니다.\n"
        )
        return Path.home() / ".okstra"
    return home


def okstra_root(project_root: Path) -> Path:
    """`<project_root>/.okstra` 절대 path."""
    return Path(project_root) / OKSTRA_RELATIVE


def project_json_path(project_root: Path) -> Path:
    """`<project_root>/.okstra/project.json` 절대 path."""
    return Path(project_root) / PROJECT_JSON_RELATIVE


def tasks_root(project_root: Path) -> Path:
    """`<project_root>/.okstra/tasks` 절대 path."""
    return Path(project_root) / TASKS_RELATIVE


def discovery_dir(project_root: Path) -> Path:
    """`<project_root>/.okstra/discovery` 절대 path."""
    return Path(project_root) / DISCOVERY_RELATIVE
