#!/usr/bin/env python3
import sys
import subprocess
import json
import os
import re
import argparse
from pathlib import Path

def run_command(cmd):
    try:
        result = subprocess.run(cmd, capture_output=True, text=True, check=True)
        return result.stdout.strip()
    except subprocess.CalledProcessError as e:
        print(f"Error executing command: {' '.join(cmd)}", file=sys.stderr)
        return None

def is_excluded(path, exclude_dirs=["Astro/", "notes/"]):
    """パスが除外対象ディレクトリに含まれているかチェックする。"""
    return any(ex in str(path) for ex in exclude_dirs)

def get_related(path, limit=3):
    """AtomicInsights を使用して関連ノートを取得する。"""
    import time
    import tempfile
    tmp = tempfile.mktemp(suffix=".json")
    eval_code = (
        f'window.AtomicInsights.getRelatedNotes("{path}",{{limit:{limit}}})'
        f'.then(r=>{{require("fs").writeFileSync("{tmp}",JSON.stringify(r,null,2))}})'
        f'.catch(e=>{{require("fs").writeFileSync("{tmp}",JSON.stringify({{error:e.message}}))}});'
        f'"started"'
    )
    run_command(["obsidian", "eval", f"code={eval_code}"])
    time.sleep(8)

    related_notes = []
    try:
        with open(tmp, "r", encoding="utf-8") as f:
            res = json.load(f)
        os.remove(tmp)
        if res.get("status") == "success":
            related_notes = res.get("results", [])
    except:
        pass

    return [r for r in related_notes if not is_excluded(r.get("path", ""))]

def main():
    parser = argparse.ArgumentParser(description="Explore related notes and append to MOC workspace.")
    parser.add_argument("query", help="Search query")
    parser.add_argument("--output", required=True, help="Path to MOC workspace markdown file.")
    args = parser.parse_args()

    query = args.query
    dest_path = Path(args.output)
    
    if not dest_path.exists():
        print(f"Error: Output file not found: {dest_path}", file=sys.stderr)
        sys.exit(1)

    output_lines = []
    print(f"--- Exploring notes for query: {query} ---")

    # 1. Search existing notes (Brainに限定)
    search_output = run_command(["obsidian", "search:context", f"query={query}", "path=Brain", "limit=10"])
    if not search_output:
        print("No notes found for query.")
        sys.exit(0)

    # search:context の結果は "filename:line:content" 形式。パスのみ抽出
    seeds_raw = [p.strip() for p in search_output.split("\n") if p.strip()]
    seeds = []
    for s in seeds_raw:
        parts = s.split(":", 1)
        if len(parts) > 0:
            path = parts[0]
            if path not in seeds:
                seeds.append(path)
    seeds = [p for p in seeds if not is_excluded(p)] # 明示的な除外
    seen_paths = set(seeds)

    output_lines.append(f"\n### Seed / 1st Hop (Query: {query})")

    for seed_path in seeds:
        print(f"\n[Seed] {seed_path}")
        seed_stem = Path(seed_path).stem
        output_lines.append(f"- [[{seed_stem}]] (Seed)")
        
        # 1-Hop
        related_1 = get_related(seed_path, limit=5)
        if not related_1:
            print("  (No 1-hop suggestions)")
            continue
            
        print("  [1st Hop Suggestions]")
        for r1 in related_1:
            r1_path = r1.get("path")
            r1_stem = Path(r1_path).stem
            score = r1.get("score", 0)
            print(f"    - [[{r1_stem}]] (score: {score:.2f})")
            output_lines.append(f"    - [[{r1_stem}]]")
            
            # 2nd Hop
            if r1_path not in seen_paths and score > 0.6:
                seen_paths.add(r1_path)
                related_2 = get_related(r1_path, limit=3)
                if related_2:
                    print(f"      ㄴ [2nd Hop from {r1_stem}]")
                    output_lines.append(f"        - (from [[{r1_stem}]])")
                    for r2 in related_2:
                        r2_path = r2.get("path")
                        if r2_path not in seen_paths:
                            r2_stem = Path(r2_path).stem
                            print(f"         - [[{r2_stem}]]")
                            output_lines.append(f"            - [[{r2_stem}]]")
                            seen_paths.add(r2_path)

    with open(dest_path, "a", encoding="utf-8") as f:
        f.write("\n" + "\n".join(output_lines) + "\n")
    print(f"\n✅ Results appended to: {dest_path}")

if __name__ == "__main__":
    main()
