from __future__ import annotations

import json
from datetime import datetime, timezone
from pathlib import Path


RUNTIME_DIRNAME = ".hallucinate"
STREAM_FILENAME = "stream.jsonl"


def workspace_root(path: str | Path | None = None) -> Path:
    base = Path(path).expanduser().resolve() if path is not None else Path.cwd().expanduser().resolve()
    return base


def runtime_dir(path: str | Path | None = None) -> Path:
    return workspace_root(path) / RUNTIME_DIRNAME


def default_stream_file(path: str | Path | None = None) -> Path:
    return runtime_dir(path) / STREAM_FILENAME


def ensure_runtime_dir(path: str | Path | None = None) -> Path:
    directory = runtime_dir(path)
    directory.mkdir(parents=True, exist_ok=True)
    return directory


def is_within_workspace(candidate: str | Path | None, root: Path | None) -> bool:
    if root is None:
        return True
    if not candidate:
        return False

    try:
        candidate_path = Path(candidate).expanduser().resolve()
        workspace = workspace_root(root)
    except OSError:
        return False

    return candidate_path == workspace or candidate_path.is_relative_to(workspace)


def append_jsonl(path: str | Path, payload: dict[str, object]) -> None:
    target = Path(path)
    target.parent.mkdir(parents=True, exist_ok=True)
    with target.open("a", encoding="utf-8", newline="\n") as handle:
        handle.write(json.dumps(payload, ensure_ascii=False, separators=(",", ":")))
        handle.write("\n")


def utc_timestamp() -> str:
    return datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
