#!/bin/bash

set -euo pipefail

source "$(dirname -- "${BASH_SOURCE[0]}")/base-test.sh"

export OMARCHY_PATH="$ROOT"
export PATH="$ROOT/bin:$PATH"

TEST_HOME=$(mktemp -d)
trap 'rm -rf "$TEST_HOME"' EXIT
export HOME="$TEST_HOME"

# Version format
version=$("$ROOT/bin/omarchy-cn-version")
[[ $version =~ ^[0-9]+\.[0-9]+\.[0-9]+.*-cn\.[0-9]+$ ]] || fail "cn version format" "$version"
pass "omarchy-cn-version reports <upstream>-cn.<release>"

# Mirror probe: dead host degrades to zeros without aborting under set -e
probe_out=$(
  set -euo pipefail
  source "$ROOT/cn/lib/mirror.sh"
  cn_mirror_probe "https://invalid.invalid.example"
)
[[ $probe_out == "0 0 unknown" ]] || fail "dead mirror probes as 0 0 unknown" "$probe_out"
pass "mirror probe degrades cleanly on dead host"

# Dev-mirror: apply china writes npm registry, unrelated keys survive re-apply
echo "save-exact=true" > "$HOME/.npmrc"
omarchy-cn-dev-mirror-apply china --target npm > /dev/null
grep -q '^registry=https://registry.npmmirror.com$' "$HOME/.npmrc" || fail "npm china registry written"
grep -q '^save-exact=true$' "$HOME/.npmrc" || fail "unrelated npmrc keys preserved"
pass "dev-mirror apply china manages npm registry non-destructively"

# Dev-mirror: cargo china installs the block, official removes it completely
omarchy-cn-dev-mirror-apply china --target cargo > /dev/null
grep -q 'replace-with = "omarchycn"' "$HOME/.cargo/config.toml" || fail "cargo china writes source replacement"
grep -q 'rsproxy.cn' "$HOME/.cargo/config.toml" || fail "cargo china points at the registry URL"
omarchy-cn-dev-mirror-apply official --target cargo > /dev/null
if grep -q "crates-io" "$HOME/.cargo/config.toml"; then
  fail "cargo official removes managed source block"
fi
pass "dev-mirror cargo china installs and official removes the block"

# IME: profile installs rime as default, hotkey surgery keeps other sections
mkdir -p "$HOME/.config/fcitx5"
cp "$ROOT/cn/fcitx5/profile" "$HOME/.config/fcitx5/profile"
grep -q '^DefaultIM=rime$' "$HOME/.config/fcitx5/profile" || fail "shipped profile defaults to rime"
printf '[Behavior]\nShareInputState=No\n\n[Hotkey/TriggerKeys]\n0=Zenkaku_Hankaku\n' > "$HOME/.config/fcitx5/config"
omarchy-cn-ime-hotkey super-space > /dev/null
grep -q '^ShareInputState=No$' "$HOME/.config/fcitx5/config" || fail "hotkey surgery preserves other sections"
grep -q '^0=Super+space$' "$HOME/.config/fcitx5/config" || fail "hotkey surgery sets trigger"
grep -q 'hl.unbind("SUPER + SPACE")' "$HOME/.config/hypr/bindings.lua" || fail "menu key unbound"
grep -q 'hl.unbind("SUPER + ALT + SPACE")' "$HOME/.config/hypr/bindings.lua" || fail "apps menu key unbound before rebind"
grep -q 'o.bind("SUPER + ALT + SPACE", "Omarchy menu"' "$HOME/.config/hypr/bindings.lua" || fail "menu rebound to Super+Alt+Space"
omarchy-cn-ime-hotkey ctrl-space > /dev/null
grep -q '^0=Control+space$' "$HOME/.config/fcitx5/config" || fail "ctrl-space restores Control+space trigger"
if grep -q 'OmarchyCN ime hotkey begin' "$HOME/.config/hypr/bindings.lua"; then
  fail "ctrl-space removes migration block"
fi
pass "ime hotkey section surgery and menu migration round-trip"

# Fontconfig priority file is well-formed and carries the required rules
python3 - "$ROOT/cn/fontconfig/64-omarchycn-cjk.conf" <<'PYEOF' || fail "fontconfig rules incomplete"
import sys
import xml.etree.ElementTree as ET
tree = ET.parse(sys.argv[1])
text = ET.tostring(tree.getroot(), encoding="unicode")
required = [
    "Noto Sans CJK SC", "Noto Serif CJK SC", "Noto Sans Mono CJK SC",
    "Noto Sans CJK JP", "Noto Sans CJK KR", "zh-cn",
]
missing = [r for r in required if r not in text]
weak_appends = [
    e for e in tree.getroot().iter("edit")
    if e.get("mode") == "append" and e.get("binding") == "weak"
]
if missing or not weak_appends:
    raise SystemExit(f"missing={missing} weak_appends={len(weak_appends)}")
PYEOF
pass "fontconfig priority file carries SC/JP/KR rules and weak fallback"

# Menu: OmarchyCN entries parse and reference only existing commands
node -e '
  const fs = require("fs");
  const src = fs.readFileSync(process.argv[1], "utf8")
    .split("\n").filter(l => !l.trim().startsWith("//")).join("\n")
    .replace(/,(\s*[}\]])/g, "$1");
  const menu = JSON.parse(src);
  const cn = Object.keys(menu).filter(k => k.startsWith("omarchycn"));
  const required = [
    "omarchycn", "omarchycn.mirrors.china", "omarchycn.mirrors.official",
    "omarchycn.mirrors.benchmark", "omarchycn.mirrors.restore",
    "omarchycn.chinese.ime", "omarchycn.chinese.fonts", "omarchycn.chinese.locale",
    "omarchycn.chinese.hotkey-ctrl", "omarchycn.chinese.hotkey-super",
    "omarchycn.display.s10", "omarchycn.display.s125", "omarchycn.display.s15",
    "omarchycn.display.s16", "omarchycn.display.s175", "omarchycn.display.s20",
    "omarchycn.diagnostics.doctor", "omarchycn.update", "omarchycn.about",
  ];
  const gone = required.filter(k => !(k in menu));
  if (gone.length) throw new Error("missing menu entries: " + gone.join(", "));
  for (const key of cn) {
    const action = menu[key].action || "";
    const m = action.match(/omarchy-cn-[a-z-]+/);
    if (m) {
      fs.accessSync(process.argv[2] + "/" + m[0], fs.constants.X_OK);
    }
  }
' "$ROOT/default/omarchy/omarchy-menu.jsonc" "$ROOT/bin" ||
  fail "OmarchyCN menu entries reference existing executable commands"
pass "OmarchyCN menu entries parse and reference real commands"
