#!/usr/bin/env python3
"""Generate the links/ folder for a workspace from its manifest.yaml.

Reads ./manifest.yaml, expands ${VAULT_ROOT}, ${OUTPUT_ROOT} and any other
${...} environment variables in the values, then writes:

    links/code        symlink to the workspace code_root
    links/renders     symlink to the first project's output_paths.renders
    links/repo.url    plain text file containing the first project's repo_url

Re-running is safe. Existing symlinks or files at those targets are removed
and rewritten so the workspace stays connected after any move. Requires
PyYAML.
"""

from __future__ import annotations

import argparse
import os
from pathlib import Path

import yaml


def expand(value: str) -> str:
    """Expand ${VAR} placeholders against the current environment."""
    return os.path.expandvars(value)


def replace_symlink(link: Path, target: Path) -> None:
    """Create or replace a symlink at link pointing to target."""
    if link.is_symlink() or link.exists():
        link.unlink()
    link.symlink_to(target)


def write_url_file(path: Path, url: str) -> None:
    """Write a plain text URL file, replacing any existing entry."""
    if path.is_symlink() or path.exists():
        path.unlink()
    path.write_text(url.strip() + "\n", encoding="utf-8")


def generate(manifest_path: Path, workspace_root: Path) -> None:
    data = yaml.safe_load(manifest_path.read_text(encoding="utf-8"))
    if not isinstance(data, dict):
        raise ValueError(f"manifest at {manifest_path} did not parse to a mapping")

    code_root = data.get("code_root")
    if not code_root:
        raise ValueError("manifest is missing required key: code_root")

    links_dir = workspace_root / "links"
    links_dir.mkdir(parents=True, exist_ok=True)

    replace_symlink(links_dir / "code", Path(expand(code_root)))

    projects = data.get("projects") or []
    if projects:
        first = projects[0]
        renders = (first.get("output_paths") or {}).get("renders")
        if renders:
            replace_symlink(links_dir / "renders", Path(expand(renders)))
        repo_url = first.get("repo_url")
        if repo_url:
            write_url_file(links_dir / "repo.url", expand(repo_url))


def main() -> None:
    parser = argparse.ArgumentParser(description="Generate workspace links from manifest.yaml")
    parser.add_argument("--manifest", default="./manifest.yaml", help="Path to manifest.yaml")
    parser.add_argument("--workspace-root", default=".", help="Workspace root where links/ is written")
    args = parser.parse_args()

    generate(Path(args.manifest).resolve(), Path(args.workspace_root).resolve())


if __name__ == "__main__":
    main()
