#!/usr/bin/env python3
"""isep-doctor — 這台機器的 Claude Code 到底有沒有把 ISEP 載進來（inkstone/ISEP#150）

為什麼要有這支：
  plugin 載入失敗時，ISEP 的 59 支閘**一支都不會跑**，而且**沒有任何閘能講出來**——
  講話的 isep-presence-beacon 本身就在那個沒載入的 plugin 裡。
  2026-09-05 起 `~/.claude/settings.json` 的 `extraKnownMarketplaces.inkstone.source`
  多了一個 `path`（本機 checkout 路徑），Claude Code 把它當成 git 來源的抓取欄位
  （debug log：「its network source differs from the one declared for it in settings
  (… path …)」），整個 marketplace 被忽略 ⇒ `isep@inkstone` 報 "Marketplace inkstone not found"。
  CLI 與 Desktop 同病，當時被誤判成「Desktop 不跑 hook」。

判準（狀態，不是措辭）：
  ① `claude plugin list --json` 裡 isep@inkstone 帶 errors ⇒ ❌
  ② settings 對 inkstone 的宣告，比 known_marketplaces.json 記的多了抓取欄位 ⇒ 指出是哪一個、給修法
  都沒有 ⇒ ✅，離開碼 0

離開碼：0 通｜1 沒載入（附原因與一行修法）｜2 查不了（找不到 claude 可執行檔等）

測試用環境變數：ISEP_DOCTOR_PLUGIN_LIST_JSON（直接給 plugin list 的輸出檔）、
ISEP_DOCTOR_CLAUDE_HOME（代替 ~/.claude）。迴歸測試：scripts/test-isep-doctor.sh
"""
import glob
import json
import os
import shutil
import subprocess
import sys

PLUGIN_ID = "isep@inkstone"
MARKET = "inkstone"
FETCH_FIELDS = ("path", "ref", "headers", "sparsePaths")

home = os.environ.get("ISEP_DOCTOR_CLAUDE_HOME") or os.path.expanduser("~/.claude")


def find_claude():
    c = shutil.which("claude")
    if c:
        return c
    cands = sorted(glob.glob(os.path.expanduser(
        "~/Library/Application Support/Claude/claude-code/*/claude.app/Contents/MacOS/claude")))
    return cands[-1] if cands else None


def plugin_list():
    f = os.environ.get("ISEP_DOCTOR_PLUGIN_LIST_JSON")
    if f:
        return json.load(open(f))
    exe = find_claude()
    if not exe:
        return None
    out = subprocess.run([exe, "plugin", "list", "--json"], capture_output=True, text=True, timeout=60)
    return json.loads(out.stdout)


def load(p):
    try:
        return json.load(open(p))
    except Exception:
        return {}


try:
    plugins = plugin_list()
except Exception as e:  # noqa: BLE001
    print(f"◐ 查不了：claude plugin list 失敗（{e}）")
    sys.exit(2)
if plugins is None:
    print("◐ 查不了：找不到 claude 可執行檔")
    sys.exit(2)

entry = next((p for p in plugins if p.get("id") == PLUGIN_ID), None)
declared = (load(os.path.join(home, "settings.json")).get("extraKnownMarketplaces") or {}).get(MARKET, {}).get("source")
known = (load(os.path.join(home, "plugins", "known_marketplaces.json")).get(MARKET) or {}).get("source")

extra = []
if isinstance(declared, dict):
    extra = [k for k in FETCH_FIELDS if k in declared and (not isinstance(known, dict) or declared.get(k) != known.get(k))]

if entry is None:
    print(f"❌ {PLUGIN_ID} 沒有安裝（這台的閘全部不存在）")
    print("   修法：claude plugin marketplace add https://git.uncle6.me/inkstone/ISEP.git && claude plugin install isep@inkstone")
    sys.exit(1)

errors = entry.get("errors") or []
if not errors and not extra:
    print(f"✅ {PLUGIN_ID} {entry.get('version')} 已載入（enabled={entry.get('enabled')}）")
    sys.exit(0)

print(f"❌ {PLUGIN_ID} {entry.get('version')} 沒有載入——這台 Claude Code（CLI 與 Desktop 都一樣）一支 ISEP 閘都不會跑")
for e in errors:
    print(f"   Claude Code 回報：{e}")
if extra:
    print(f"   原因：~/.claude/settings.json 的 extraKnownMarketplaces.{MARKET}.source 多了 {', '.join(extra)}，"
          "Claude Code 把它當 git 抓取欄位，跟已安裝的 marketplace 對不上，整個 marketplace 被忽略")
    fields = ", ".join(repr(k) for k in extra)
    print("   修法（一行，改完重開 Claude Desktop／CLI session）：")
    print(f"   python3 -c \"import json,os;p=os.path.expanduser('~/.claude/settings.json');d=json.load(open(p));"
          f"s=d['extraKnownMarketplaces']['{MARKET}']['source'];[s.pop(k,None) for k in ({fields},)];"
          "json.dump(d,open(p,'w'),ensure_ascii=False,indent=2)\"")
sys.exit(1)
