#!/usr/bin/env bash
# clean_n1_zone
#
# 跨環境（N1-JP / N1-EN / N1-TW）hosts + known_hosts 清理工具。
#
# 設計：完全依靠 hosts 內的 zone 註解 (S<zone_id>) + alias 比對，
# 不依賴任何 IP prefix；所有環境走同一條 code path。
#
# 用法:
#   clean_n1_zone [--dry-run|-n] <Zone ID>
#
# Zone ID:
#   0        全砍（AccountDB + 所有 GameDB/WorldDB + Zone 註解，保留 TEMPLATE/CTRL）
#   1        只清 AccountDB 行
#   10+      清除指定 Zone（by Set，靠 hosts 註解 (S<zone>) 區塊定位）
#
# 範例:
#   clean_n1_zone 0
#   clean_n1_zone 11
#   clean_n1_zone --dry-run 33
#

usage() {
    cat <<EOF
用法: $(basename "$0") [--dry-run|-n] <Zone ID>

Flags:
  --dry-run, -n   只列出會被刪除的行 / key，不真改 hosts、不清 known_hosts
  -h, --help      顯示本說明

Zone ID:
  0          全砍（AccountDB + 所有 GameDB/WorldDB + Zone 註解，保留 TEMPLATE/CTRL）
  1          只清 AccountDB 行
  10+        清除指定 Zone（by Set，靠 hosts 註解 (S<zone>) 區塊定位）

範例:
  $(basename "$0") 0
  $(basename "$0") 1
  $(basename "$0") --dry-run 11
  $(basename "$0") 33

設計：腳本完全不依賴 IP prefix，跨 N1-JP / N1-EN / N1-TW 通用。
EOF
    exit 1
}

DRY_RUN=false
ARGS=()
for arg in "$@"; do
    case "$arg" in
        --dry-run|-n) DRY_RUN=true ;;
        -h|--help)    usage ;;
        *)            ARGS+=("$arg") ;;
    esac
done
[[ ${#ARGS[@]} -ne 1 ]] && usage

ZONE_ID="${ARGS[0]}"

# 參數驗證：只接受 0, 1, 或 10 以上的數字
if ! [[ "$ZONE_ID" =~ ^[0-9]+$ ]]; then
    echo "錯誤：Zone ID 必須是數字，收到 '${ZONE_ID}'"
    echo ""
    usage
fi
if [[ "$ZONE_ID" -ge 2 && "$ZONE_ID" -le 9 ]]; then
    echo "錯誤：Zone ID ${ZONE_ID} 不合法（合法值：0, 1, 10+）"
    echo ""
    usage
fi

HOSTS_FILE="$HOME/bin/hosts"
KNOWN_HOSTS="$HOME/.ssh/known_hosts"
TMPFILE=$(mktemp)

DRY_FLAG="0"
if $DRY_RUN; then
    DRY_FLAG="1"
    echo "▶ DRY-RUN MODE：只列出會被刪除的行 / key，不真改檔"
    echo ""
fi

# ─────────────────────────────────────────────────────────────
# Zone 0: 全砍
# ─────────────────────────────────────────────────────────────
if [[ "$ZONE_ID" == "0" ]]; then
    echo "======================================================"
    echo " clean_n1_zone Zone ID: 0 (全砍)"
    echo " 保留: TEMPLATE, CTRL, header/footer 註解"
    echo "======================================================"

    echo ""
    echo "[Step 1] 清除 ${HOSTS_FILE} 中所有遊戲伺服器行與 Zone 註解..."

    if [[ ! -f "$HOSTS_FILE" ]]; then
        echo "  找不到 ${HOSTS_FILE}，略過"
    else
        python3 - "$HOSTS_FILE" "$TMPFILE" "$DRY_FLAG" <<'PYEOF'
import sys, shutil

hosts_file = sys.argv[1]
tmpfile    = sys.argv[2]
dry_run    = sys.argv[3] == "1"

KEEP_ALIASES = {"TEMPLATE", "CTRL"}
HEADER_MARK = "DO NOT CHANGE THE SERVER NAMES BELOW"
FOOTER_MARK = "DO NOT CHANGE THE SERVER NAMES ABOVE"

lines = open(hosts_file).read().splitlines()
new_lines = []
removed = 0
targets = []
in_block = False
prefix = "會刪" if dry_run else "刪除"

for line in lines:
    stripped = line.strip()

    if HEADER_MARK in stripped:
        in_block = True
        new_lines.append(line)
        continue
    if FOOTER_MARK in stripped:
        in_block = False
        new_lines.append(line)
        continue

    if not in_block:
        new_lines.append(line)
        continue

    if not stripped:
        new_lines.append(line)
        continue

    if stripped.startswith("#"):
        if stripped.startswith("## "):
            print(f"  [{prefix}] {line}")
            removed += 1
        else:
            new_lines.append(line)
        continue

    parts = stripped.split()
    aliases = set(parts[1:]) if len(parts) > 1 else set()

    if aliases & KEEP_ALIASES:
        new_lines.append(line)
        continue

    print(f"  [{prefix}] {line}")
    removed += 1
    for token in parts:
        targets.append(token)
        lower = token.lower()
        if lower != token:
            targets.append(lower)

if not dry_run:
    shutil.copy2(hosts_file, f"{hosts_file}.bak0")
    output = "\n".join(new_lines)
    if not output.endswith("\n"):
        output += "\n"
    open(hosts_file, "w").write(output)

print(f"  完成，{prefix} {removed} 行")

if not dry_run:
    with open(tmpfile, "w") as f:
        for t in targets:
            f.write(t + "\n")
else:
    print(f"  收集到 {len(targets)} 個 target（dry-run 不清 known_hosts）")
PYEOF
    fi

# ─────────────────────────────────────────────────────────────
# Zone 1: 只清 AccountDB 行
# ─────────────────────────────────────────────────────────────
elif [[ "$ZONE_ID" == "1" ]]; then
    echo "======================================================"
    echo " clean_n1_zone Zone ID: 1 (AccountDB only)"
    echo " 匹配關鍵字: ACCOUNTDB"
    echo "======================================================"

    echo ""
    echo "[Step 1] 清除 ${HOSTS_FILE} 中含 ACCOUNTDB 的行..."

    if [[ ! -f "$HOSTS_FILE" ]]; then
        echo "  找不到 ${HOSTS_FILE}，略過"
    else
        python3 - "$HOSTS_FILE" "$TMPFILE" "$DRY_FLAG" <<'PYEOF'
import sys, shutil

hosts_file = sys.argv[1]
tmpfile    = sys.argv[2]
dry_run    = sys.argv[3] == "1"

lines = open(hosts_file).read().splitlines()
new_lines = []
removed = 0
targets = []
prefix = "會刪" if dry_run else "刪除"

for line in lines:
    stripped = line.strip()
    if not stripped or stripped.startswith("#"):
        new_lines.append(line)
        continue

    parts = stripped.split()
    if "ACCOUNTDB" in parts:
        print(f"  [{prefix}] {line}")
        removed += 1
        for token in parts:
            targets.append(token)
            lower = token.lower()
            if lower != token:
                targets.append(lower)
        continue

    new_lines.append(line)

if not dry_run:
    shutil.copy2(hosts_file, f"{hosts_file}.bak1")
    output = "\n".join(new_lines)
    if not output.endswith("\n"):
        output += "\n"
    open(hosts_file, "w").write(output)

print(f"  完成，{prefix} {removed} 行")

if not dry_run:
    with open(tmpfile, "w") as f:
        for t in targets:
            f.write(t + "\n")
else:
    print(f"  收集到 {len(targets)} 個 target（dry-run 不清 known_hosts）")
PYEOF
    fi

# ─────────────────────────────────────────────────────────────
# Zone 10+: 用 hosts 的 (S<zone>) 註解區塊定位（不依賴 IP prefix）
# ─────────────────────────────────────────────────────────────
else
    echo "======================================================"
    echo " clean_n1_zone Zone ID: ${ZONE_ID}"
    echo " 模式: zone 註解區塊偵測 ## ... (S${ZONE_ID})"
    echo "======================================================"

    echo ""
    echo "[Step 1] 從 ${HOSTS_FILE} 找 (S${ZONE_ID}) 區塊..."

    if [[ ! -f "$HOSTS_FILE" ]]; then
        echo "  找不到 ${HOSTS_FILE}，略過"
    else
        python3 - "$HOSTS_FILE" "$ZONE_ID" "$TMPFILE" "$DRY_FLAG" <<'PYEOF'
import sys, re, shutil

hosts_file = sys.argv[1]
zone_id    = int(sys.argv[2])
tmpfile    = sys.argv[3]
dry_run    = sys.argv[4] == "1"

zone_marker = re.compile(rf'\(S{zone_id}\)')

lines = open(hosts_file).read().splitlines()
new_lines = []
removed = 0
targets = []
in_target = False
prefix = "會刪" if dry_run else "刪除"

for line in lines:
    stripped = line.strip()

    # ## section header 偵測（區塊邊界）
    if stripped.startswith('##'):
        if zone_marker.search(stripped):
            in_target = True
            print(f"  [{prefix}] {line}")
            removed += 1
            continue
        else:
            in_target = False
            new_lines.append(line)
            continue

    if in_target:
        # 區塊內：空行刪除（避免留下空 hole），子註解 (# ) 保留，資料行刪除
        if not stripped:
            print(f"  [{prefix}] (empty line)")
            removed += 1
            continue
        if stripped.startswith('#'):
            new_lines.append(line)
            continue
        # 資料行
        print(f"  [{prefix}] {line}")
        removed += 1
        for token in stripped.split():
            targets.append(token)
            lower = token.lower()
            if lower != token:
                targets.append(lower)
        continue

    new_lines.append(line)

if removed == 0:
    print(f"  ⚠ 沒找到 (S{zone_id}) 區塊，hosts 沒有匹配內容")

if not dry_run:
    shutil.copy2(hosts_file, f"{hosts_file}.bak{zone_id}")
    output = "\n".join(new_lines)
    if not output.endswith("\n"):
        output += "\n"
    open(hosts_file, "w").write(output)

print(f"  完成，{prefix} {removed} 行")

if not dry_run:
    with open(tmpfile, "w") as f:
        for t in targets:
            f.write(t + "\n")
else:
    print(f"  收集到 {len(targets)} 個 target（dry-run 不清 known_hosts）")
PYEOF
    fi
fi

# ─────────────────────────────────────────────────────────────
# Step 2: 清除 known_hosts
# ─────────────────────────────────────────────────────────────
echo ""
if $DRY_RUN; then
    echo "[Step 2] [dry-run] 跳過 known_hosts 清理"
else
    echo "[Step 2] 清除 ${KNOWN_HOSTS}（IP & 所有 alias）..."

    if [[ ! -f "$KNOWN_HOSTS" ]]; then
        echo "  找不到 ${KNOWN_HOSTS}，略過"
    elif [[ ! -s "$TMPFILE" ]]; then
        echo "  無收集到任何 target，略過"
    else
        REMOVED=0
        while IFS= read -r target; do
            [[ -z "$target" ]] && continue
            result=$(ssh-keygen -f "$KNOWN_HOSTS" -R "$target" 2>&1)
            if echo "$result" | grep -q "updated"; then
                echo "  [刪除] $target"
                (( REMOVED++ ))
            fi
        done < "$TMPFILE"
        echo "  完成，共清除 ${REMOVED} 筆"
    fi
fi

rm -f "$TMPFILE"

echo ""
echo "======================================================"
SUFFIX=""
$DRY_RUN && SUFFIX=" (dry-run)"
echo " Zone ${ZONE_ID} 清除${SUFFIX}完成"
echo "======================================================"
