#!/bin/bash
# Heptapick 桌面启动器
#
# 用你自己的浏览器配置，以「应用窗口」模式打开扩展面板。
#
# 为什么不做成 Electron 那种独立程序：
#   这个产品能成立，靠的就是跑在你已登录的真实浏览器里。
#   实测服务器端抓取全线被挡，连在沃尔玛自己页面里发同源请求都被挡回挑战页。
#   独立程序有自己的 cookie 罐，会丢掉登录态——Costco 会员价看不到、
#   亚马逊按配送地址给的币种也会变，还更容易被反爬识别。
#   所以外壳做成桌面程序，内核仍然借用你的浏览器。
#
# 支持所有 Chromium 系浏览器（Chrome / Edge / Brave / Arc / Vivaldi / Opera / Chromium）。
# 装在哪个浏览器里就用哪个；装在多个里就用先找到的那个。

set -u

# —— 上架浏览器商店后填这两项 ——
# STORE_EXT_ID：商店分配的固定扩展 ID（32 个小写字母）。填了就按它优先匹配，最稳。
#   ⚠️ 商店的 ID 和开发者模式下的 ID 不是同一个：未打包扩展的 ID 由安装路径推导，
#   商店的 ID 由上传包的公钥决定。所以上架后必须回来把这里填上。
# STORE_URL：商店页地址，用户没装扩展时直接引导过去。
# 两项都留空时，启动器仍然可用（按扩展名匹配），提示语会退回手动安装步骤。
STORE_EXT_ID=""
STORE_URL=""

# 浏览器名 | 应用路径 | 配置目录（相对 ~/Library/Application Support）
BROWSERS=(
  "Google Chrome|/Applications/Google Chrome.app|Google/Chrome"
  "Microsoft Edge|/Applications/Microsoft Edge.app|Microsoft Edge"
  "Brave Browser|/Applications/Brave Browser.app|BraveSoftware/Brave-Browser"
  "Arc|/Applications/Arc.app|Arc/User Data"
  "Vivaldi|/Applications/Vivaldi.app|Vivaldi"
  "Opera|/Applications/Opera.app|com.operasoftware.Opera"
  "Chromium|/Applications/Chromium.app|Chromium"
)

FOUND_APP=""; FOUND_BIN=""; FOUND_PROFILE=""; FOUND_EXT=""; FOUND_NAME=""
INSTALLED_NAMES=""

for entry in "${BROWSERS[@]}"; do
  name="${entry%%|*}"; rest="${entry#*|}"
  apppath="${rest%%|*}"; support="${rest#*|}"
  [ -d "$apppath" ] || apppath="$HOME/Applications/$name.app"
  [ -d "$apppath" ] || continue
  INSTALLED_NAMES="$INSTALLED_NAMES $name"

  # 扩展 ID 每次启动现读，不写死——重装扩展或挪动文件夹都不用改这个脚本。
  #
  # 三种匹配方式，按可靠性排序（商店安装与开发者模式都要认）：
  #   1. 商店 ID —— 填了就用它，最准
  #   2. 扩展名 —— 商店安装的路径是 <扩展ID>/<版本>_0，不含项目目录名，
  #      只靠路径匹配会导致「装好了却说没装」，所以主力靠名字
  #   3. 路径后缀 —— 开发者模式加载的老办法，留作兜底
  #
  # ⚠️ 名字必须去扩展目录里读 manifest.json，不能读 Preferences：
  #    实测 Chrome 在 extensions.settings 里**根本不存 manifest 字段**
  #    （本机这个扩展的记录里只有 path/location/from_webstore… 没有 manifest）。
  #    两种安装的 path 形状不同，拼法也不同：
  #      开发者模式：绝对路径          -> <path>/manifest.json
  #      商店安装：  <扩展ID>/<版本>_0 -> <配置目录>/Extensions/<path>/manifest.json
  # 被停用的扩展排到最后：有别的候选就不用它，实在只有它才用（至少能给出提示）。
  res=$(SUPPORT_DIR="$HOME/Library/Application Support/$support" STORE_ID="$STORE_EXT_ID" python3 - <<'PY' 2>/dev/null
import json, os, glob
base = os.environ["SUPPORT_DIR"]
store_id = os.environ.get("STORE_ID", "").strip()
WANT_NAME = "Heptapick"        # 按品牌名做子串匹配，改中文副标题或本地化都不影响
PATH_SUFFIX = "七维选品/extension"

def ext_name(profile_dir, path):
    """去扩展目录读 manifest.json 里的 name。读不到就返回空串。"""
    root = path if os.path.isabs(path) else os.path.join(profile_dir, "Extensions", path)
    try:
        with open(os.path.join(root, "manifest.json"), encoding="utf-8") as fh:
            return str(json.load(fh).get("name") or "")
    except Exception:
        return ""

best = None                                    # (rank, id, profile)：rank 越小越优先
if os.path.isdir(base):
    profiles = ["Default"] + [os.path.basename(p) for p in sorted(glob.glob(os.path.join(base, "Profile *")))]
    for prof in profiles:
        p = os.path.join(base, prof)
        for fn in ("Secure Preferences", "Preferences"):
            f = os.path.join(p, fn)
            if not os.path.exists(f):
                continue
            try:
                d = json.load(open(f))
            except Exception:
                continue
            for k, v in ((d.get("extensions") or {}).get("settings") or {}).items():
                if not isinstance(v, dict):
                    continue
                path = str(v.get("path", "")).rstrip("/")
                if store_id and k == store_id:
                    rank = 0
                elif WANT_NAME in ext_name(p, path):
                    rank = 1
                elif path.endswith(PATH_SUFFIX):
                    rank = 2
                else:
                    continue
                if v.get("state", 1) != 1:      # 0 = 用户把它停用了
                    rank += 10
                if best is None or rank < best[0]:
                    best = (rank, k, prof)
if best:
    print(best[1] + "\t" + best[2])
PY
)
  if [ -n "$res" ]; then
    FOUND_NAME="$name"; FOUND_APP="$apppath"
    FOUND_BIN="$apppath/Contents/MacOS/$(defaults read "$apppath/Contents/Info" CFBundleExecutable 2>/dev/null)"
    FOUND_EXT=$(printf '%s' "$res" | cut -f1)
    FOUND_PROFILE=$(printf '%s' "$res" | cut -f2)
    break
  fi
done

if [ -z "$FOUND_EXT" ]; then
  if [ -z "$INSTALLED_NAMES" ]; then
    osascript -e 'display alert "找不到支持的浏览器" message "Heptapick 需要一个 Chromium 系浏览器：Chrome、Edge、Brave、Arc、Vivaldi、Opera 或 Chromium。请先装一个。" as critical'
  elif [ -n "$STORE_URL" ]; then
    # 已经上架：直接把人送到商店页，别再讲开发者模式那一套
    osascript -e "display alert \"还没装 Heptapick 扩展\" message \"已找到这些浏览器：$INSTALLED_NAMES

点「打开商店」安装 Heptapick，装好后再打开本程序。\" buttons {\"取消\", \"打开商店\"} default button \"打开商店\"" >/dev/null 2>&1 \
      && open "$STORE_URL"
  else
    osascript -e "display alert \"还没装 Heptapick 扩展\" message \"已找到这些浏览器：$INSTALLED_NAMES

请在其中一个里打开 扩展管理页（chrome://extensions 或 edge://extensions），开启开发者模式，用「加载未打包的扩展程序」选中 七维选品/extension 文件夹，然后再打开本程序。\" as critical"
  fi
  exit 1
fi

[ -x "$FOUND_BIN" ] || FOUND_BIN="$FOUND_APP/Contents/MacOS/$FOUND_NAME"

exec "$FOUND_BIN" \
  --profile-directory="$FOUND_PROFILE" \
  --app="chrome-extension://${FOUND_EXT}/src/panel/panel.html" \
  --window-size=430,940
