#!/usr/bin/env bash
#
# Remove a worktree created by worktree-create.sh: tear down its Docker
# stack (including its data volume), remove the git worktree, drop its
# port-registry entry, and optionally delete the branch.
#
# Usage:
#   ./scripts/worktree-teardown.sh <dir-name>
#   ./scripts/worktree-teardown.sh <dir-name> --delete-branch

set -euo pipefail

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'

DIR_NAME="${1:-}"
DELETE_BRANCH=false
[[ "${2:-}" == "--delete-branch" ]] && DELETE_BRANCH=true

[[ -z "$DIR_NAME" ]] && { echo -e "${RED}Usage: $0 <dir-name> [--delete-branch]${NC}"; exit 1; }
# Reject path separators / traversal so we only ever operate on a single
# directory directly under worktrees/ (a typo like DIR=../foo must not escape).
[[ "$DIR_NAME" == *"/"* || "$DIR_NAME" == *".."* ]] && { echo -e "${RED}Error: invalid dir-name '$DIR_NAME' (no '/' or '..')${NC}"; exit 1; }

REPO_ROOT="$(git rev-parse --show-toplevel)"
PARENT_DIR="$REPO_ROOT/worktrees"
WORKTREE_DIR="$PARENT_DIR/$DIR_NAME"
PORT_REGISTRY="$PARENT_DIR/.port-registry"
PORT_LOCK="$PARENT_DIR/.port-lock"

[[ -d "$WORKTREE_DIR" ]] || { echo -e "${RED}Error: $WORKTREE_DIR does not exist${NC}"; exit 1; }

# Resolve the branch before we remove the worktree, so --delete-branch works.
BRANCH_NAME="$(git -C "$WORKTREE_DIR" rev-parse --abbrev-ref HEAD 2>/dev/null || true)"

# ── Tear down the stack (drops the unique named volume too) ──────────────────
echo -e "${YELLOW}Tearing down Docker stack…${NC}"
( cd "$WORKTREE_DIR" && docker compose down -v 2>/dev/null ) || \
    echo -e "${YELLOW}⚠ compose down reported an issue (stack may already be down)${NC}"

# ── Remove the git worktree ──────────────────────────────────────────────────
# --force is needed to remove a worktree with the untracked local files this
# tool creates (.env, .snag.md), but it also discards genuine uncommitted work.
# Warn and confirm when the worktree is dirty so nobody loses code silently.
echo -e "${YELLOW}Removing git worktree…${NC}"
# --untracked-files=no so the tool's own generated files (.env, .snag.md,
# published assets) don't trip the guard on every teardown — we only prompt
# when tracked files have real, uncommitted modifications.
if [[ -n "$(git -C "$WORKTREE_DIR" status --porcelain --untracked-files=no 2>/dev/null)" ]]; then
    echo -e "${YELLOW}⚠ Worktree has uncommitted changes to tracked files.${NC}"
    read -r -p "Remove anyway and discard them? [y/N] " confirm
    [[ "$confirm" =~ ^[Yy]$ ]] || { echo "Aborted."; exit 1; }
fi
git worktree remove "$WORKTREE_DIR" --force

# ── Drop the port-registry entry (locked) ────────────────────────────────────
if [[ -f "$PORT_REGISTRY" ]]; then
    exec 9>"$PORT_LOCK"
    flock 9
    grep -v "^${DIR_NAME} " "$PORT_REGISTRY" > "${PORT_REGISTRY}.tmp" 2>/dev/null || true
    mv "${PORT_REGISTRY}.tmp" "$PORT_REGISTRY"
    flock -u 9
    exec 9>&-
fi

# ── Optionally delete the branch ─────────────────────────────────────────────
if [[ "$DELETE_BRANCH" == true && -n "$BRANCH_NAME" && "$BRANCH_NAME" != "HEAD" ]]; then
    echo -e "${YELLOW}Deleting branch $BRANCH_NAME…${NC}"
    git branch -D "$BRANCH_NAME" 2>/dev/null || \
        echo -e "${YELLOW}⚠ could not delete branch $BRANCH_NAME${NC}"
fi

echo -e "${GREEN}✓ Removed worktree '$DIR_NAME'${NC}"
[[ "$DELETE_BRANCH" == true ]] || echo "  Branch '$BRANCH_NAME' kept (pass --delete-branch to remove it)."
