#!/usr/bin/env bash

set -eo pipefail

REPO_ROOT="${WARP_COMMON_SKILLS_TARGET_REPO_ROOT:-$(pwd)}"
LOCK_FILE=""
STAMP_RELATIVE_PATH="warp/common-skills-lock.hash"
CLEAR_LOCK=0

TARGET="${WARP_COMMON_SKILLS_INSTALL_TARGET:-project}"

resolve_repo_root() {
  cd "$1" && pwd
}

project_stamp_file() {
  local git_path=""

  if git_path="$(git -C "${REPO_ROOT}" rev-parse --git-path "${STAMP_RELATIVE_PATH}" 2>/dev/null)"; then
    case "${git_path}" in
      /*)
        echo "${git_path}"
        ;;
      *)
        echo "${REPO_ROOT}/${git_path}"
        ;;
    esac
    return
  fi

  echo "${REPO_ROOT}/.agents/skills/.common-skills-lock.hash"
}

project_exclude_file() {
  local git_path=""

  if git_path="$(git -C "${REPO_ROOT}" rev-parse --git-path "info/exclude" 2>/dev/null)"; then
    case "${git_path}" in
      /*)
        echo "${git_path}"
        ;;
      *)
        echo "${REPO_ROOT}/${git_path}"
        ;;
    esac
    return
  fi

  return 1
}

global_stamp_file() {
  echo "${HOME}/.agents/warp/common-skills-lock.hash"
}

stamp_file() {
  if [[ "${TARGET}" = "global" ]]; then
    global_stamp_file
  else
    project_stamp_file
  fi
}

normalize_common_skills_target() {
  local target
  target="$(printf "%s" "$1" | tr '[:upper:]' '[:lower:]')"

  case "${target}" in
    ""|p|project|1)
      echo "project"
      ;;
    g|global|2)
      echo "global"
      ;;
    *)
      return 1
      ;;
  esac
}

locked_skill_names() {
  node -e '
const fs = require("fs");
const lock = JSON.parse(fs.readFileSync(process.argv[1], "utf8"));
for (const name of Object.keys(lock.skills || {})) {
  console.log(name);
}
' "${LOCK_FILE}"
}

locked_skill_paths() {
  node -e '
const fs = require("fs");
const lock = JSON.parse(fs.readFileSync(process.argv[1], "utf8"));
for (const skill of Object.values(lock.skills || {})) {
  console.log(skill.skillPath);
}
' "${LOCK_FILE}"
}

target_description() {
  if [[ "${TARGET}" = "global" ]]; then
    echo "~/.agents/skills"
  else
    echo ".agents/skills"
  fi
}

validate_required_commands() {
  local missing=0
  local tool=""

  for tool in "$@"; do
    if ! command -v "${tool}" >/dev/null 2>&1; then
      echo "error: required command '${tool}' is not installed or not on PATH." >&2
      missing=1
    fi
  done

  if [[ "${missing}" -eq 1 ]]; then
    echo "Install the missing tools, then rerun scripts/remove_common_skills." >&2
    exit 1
  fi
}

usage() {
  cat <<EOF
Usage: scripts/remove_common_skills [options]

Remove common agent skills listed in the standard project skills-lock.json.

Options:
  --repo-root <path>   Repository containing skills-lock.json and project skills.
  --project            Remove from this checkout's .agents/skills directory (default).
  --global             Remove from ~/.agents/skills for the current user.
  --clear-lock         Also remove skills-lock.json after removing locked skills.
  -h, --help           Show this help message.

Environment:
  WARP_COMMON_SKILLS_INSTALL_TARGET=project|global
      Choose the removal target when no explicit --project/--global flag is provided.
  WARP_COMMON_SKILLS_TARGET_REPO_ROOT=/path/to/repo
      Repository containing skills-lock.json and project-local .agents/skills.
EOF
}

remove_project_from_lock() {
  local path=""
  local skill_dir=""

  while IFS= read -r path; do
    if [[ -z "${path}" ]]; then
      continue
    fi

    case "${path}" in
      .agents/skills/*/SKILL.md)
        skill_dir="$(dirname "${REPO_ROOT}/${path}")"
        ;;
      *)
        echo "error: refusing to remove unexpected skill path from lock file: ${path}" >&2
        exit 1
        ;;
    esac

    case "${skill_dir}" in
      "${REPO_ROOT}/.agents/skills/"*)
        rm -rf -- "${skill_dir}"
        ;;
      *)
        echo "error: refusing to remove path outside .agents/skills: ${skill_dir}" >&2
        exit 1
        ;;
    esac
  done < <(locked_skill_paths)
}

remove_global_from_lock() {
  local name=""
  local skill_dir=""

  while IFS= read -r name; do
    if [[ -z "${name}" ]]; then
      continue
    fi

    case "${name}" in
      */*|.|..)
        echo "error: refusing to remove unexpected skill name from lock file: ${name}" >&2
        exit 1
        ;;
    esac

    skill_dir="${HOME}/.agents/skills/${name}"
    rm -rf -- "${skill_dir}"
  done < <(locked_skill_names)
}

remove_from_lock() {
  if [[ "${TARGET}" = "global" ]]; then
    remove_global_from_lock
  else
    remove_project_from_lock
    remove_project_common_skills_ignore_block
  fi

  rm -f -- "$(stamp_file)"
}

remove_project_common_skills_ignore_block() {
  local exclude_file=""
  local tmp_file=""
  local marker_start="# BEGIN warp common-skills"
  local marker_end="# END warp common-skills"

  if ! exclude_file="$(project_exclude_file)"; then
    return 0
  fi

  if [[ ! -f "${exclude_file}" ]]; then
    return 0
  fi

  tmp_file="$(mktemp)"
  awk -v start="${marker_start}" -v end="${marker_end}" '
    $0 == start { skipping = 1; next }
    $0 == end { skipping = 0; next }
    !skipping { print }
  ' "${exclude_file}" > "${tmp_file}"
  cat "${tmp_file}" > "${exclude_file}"
  rm -f "${tmp_file}"
}

while [[ $# -gt 0 ]]; do
  case "$1" in
    --repo-root)
      if [[ -n "${2:-}" ]]; then
        REPO_ROOT="$2"
        shift 2
      else
        echo "error: argument for $1 is missing" >&2
        usage >&2
        exit 1
      fi
      ;;
    --project)
      TARGET="project"
      shift
      ;;
    --global)
      TARGET="global"
      shift
      ;;
    --clear-lock)
      CLEAR_LOCK=1
      shift
      ;;
    -h|--help)
      usage
      exit 0
      ;;
    *)
      echo "error: unknown argument: $1" >&2
      usage >&2
      exit 1
      ;;
  esac
done

if ! REPO_ROOT="$(resolve_repo_root "${REPO_ROOT}")"; then
  echo "error: repo root does not exist: ${REPO_ROOT}" >&2
  exit 1
fi
LOCK_FILE="${REPO_ROOT}/skills-lock.json"

if [[ "${TARGET}" != "project" && "${TARGET}" != "global" ]]; then
  echo "error: invalid common skills removal target: ${TARGET} (expected project or global)" >&2
  usage >&2
  exit 1
fi

if [[ ! -f "${LOCK_FILE}" ]]; then
  if [[ "${CLEAR_LOCK}" -eq 1 ]]; then
    echo "Skills lock file is already absent: ${LOCK_FILE}"
    exit 0
  fi
  echo "error: missing skills lock file: ${LOCK_FILE}" >&2
  exit 1
fi
validate_required_commands git node

echo "Removing common agent skills listed in skills-lock.json from $(target_description)."
remove_from_lock
if [[ "${CLEAR_LOCK}" -eq 1 ]]; then
  rm -f -- "${LOCK_FILE}"
fi
