# -*- coding: utf-8 -*-
"""Install the Felhom Claude Code skills from <repo>/skills/ into ~/.claude/skills/.

Usage:  python3 scripts/install_skills.py           (run from the felhom.eu repo root or anywhere)

Personal skills (~/.claude/skills/) apply across all projects — the right scope for the 4-repo
felhom workspace. Preferred install is a LINK so edits in the repo are live immediately: a POSIX
symlink on Linux/macOS (the DooPlex environment), a junction (mklink /J) on Windows. If the link
cannot be created or isn't followed, falls back to a full COPY — in copy mode you must RE-RUN this
script after editing skills/. Idempotent: safe to re-run any time.
"""
import os, shutil, subprocess, sys

REPO = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
SRC = os.path.join(REPO, "skills")
DST = os.path.join(os.path.expanduser("~"), ".claude", "skills")

fails = 0
copy_mode_used = False


IS_WINDOWS = os.name == "nt"
LINK_KIND = "junction" if IS_WINDOWS else "symlink"


def is_working_link(target, src):
    """True if target resolves into src (junction/symlink already correct)."""
    try:
        return os.path.isfile(os.path.join(target, "SKILL.md")) and \
            os.path.samefile(os.path.join(target, "SKILL.md"), os.path.join(src, "SKILL.md"))
    except OSError:
        return False


def remove_existing(target):
    # a link must be removed WITHOUT recursing INTO it (that would delete the repo's skills);
    # a real copied directory needs rmtree
    if os.path.islink(target):
        os.unlink(target)  # POSIX symlink (also a Windows symlink-to-dir)
        return
    try:
        os.rmdir(target)  # works for Windows junctions and empty dirs
    except OSError:
        shutil.rmtree(target, ignore_errors=True)


def make_link(target, src):
    """Create the platform's live link. Returns (ok, detail-for-humans)."""
    if IS_WINDOWS:
        r = subprocess.run(["cmd", "/c", "mklink", "/J", target, src],
                           capture_output=True, text=True)
        if r.returncode != 0:
            return False, (r.stderr or r.stdout).strip() or "mklink failed"
        return True, ""
    try:
        os.symlink(src, target, target_is_directory=True)
        return True, ""
    except OSError as e:
        return False, str(e)


def install(name):
    global fails, copy_mode_used
    src = os.path.join(SRC, name)
    target = os.path.join(DST, name)
    if os.path.lexists(target):
        if is_working_link(target, src):
            print("OK   %-22s %s (already installed, live-linked to repo)" % (name, LINK_KIND))
            return
        remove_existing(target)
    ok, detail = make_link(target, src)
    if ok and is_working_link(target, src):
        print("OK   %-22s %s -> %s" % (name, LINK_KIND, src))
        return
    if not ok:
        reason = detail
    else:
        reason = "not followed"
    # fall back to copy
    if os.path.lexists(target):
        remove_existing(target)
    try:
        shutil.copytree(src, target)
        copy_mode_used = True
        print("OK   %-22s COPY (%s failed: %s)" % (name, LINK_KIND, reason))
    except OSError as e:
        fails += 1
        print("FAIL %-22s %s" % (name, e))


if not os.path.isdir(SRC):
    print("FAIL: no skills/ dir at %s" % SRC)
    sys.exit(2)
os.makedirs(DST, exist_ok=True)
names = sorted(d for d in os.listdir(SRC) if os.path.isfile(os.path.join(SRC, d, "SKILL.md")))
if not names:
    print("FAIL: no skills found under %s" % SRC)
    sys.exit(2)
for n in names:
    install(n)
if copy_mode_used:
    print("\nNOTE: copy mode active for at least one skill — RE-RUN this script after editing skills/.")
sys.exit(1 if fails else 0)
