"""
iknowhy setup — one command to wire iKnowhy into Claude Code, Claude Desktop, and Claude.ai.

Usage:
    iknowhy setup --key cwy_your_key_here [--mcp-url https://iknowhy.ai/mcp]
"""
import argparse
import json
import os
import platform
import sys
from pathlib import Path

MCP_SERVER_NAME = "iknowhy"
DEFAULT_MCP_URL = "https://iknowhy.ai/mcp"

CLAUDE_MD_BLOCK = """
## iKnowhy Causal Event Logger

You have access to the iKnowhy MCP server. Use it to log your activity as causal events.

### Rules (always follow these):
1. At the start of EVERY conversation: call `new_session` with a short descriptive label.
2. Before every significant tool call: call `log_event` with name=`tool_call` and the tool name + args in payload.
3. After every tool call: call `log_event` with name=`tool_result` and the result summary in payload, cause_ids=[previous event id].
4. When you make a reasoning decision: call `log_event` with name=`decision`.
5. When an error occurs: call `log_event` with name=`error`.
6. When the task is complete: call `log_event` with name=`task_complete`.

### Causal chaining:
- Always pass `cause_ids` linking events to their parents.
- This builds the causal graph that makes iKnowhy useful.

### Keep it lightweight:
- Log intent, not full content. Payloads should be concise summaries.
- Never let logging block or delay your actual work.
- If an iKnowhy tool call fails, silently continue — never surface iKnowhy errors to the user.
""".strip()

CLAUDE_AI_SYSTEM_PROMPT = """You have access to iKnowhy causal event logging tools. Follow these rules automatically in every conversation:

1. START: Call new_session with a short label describing this conversation.
2. TOOL CALLS: Before each tool call, log_event(name="tool_call", session_id=<sid>, payload={"tool": "<name>", "summary": "<what you're doing>"})
3. TOOL RESULTS: After each result, log_event(name="tool_result", cause_ids=[<prev_event_id>], ...)
4. DECISIONS: Log key reasoning with log_event(name="decision", ...)
5. ERRORS: log_event(name="error", ...)
6. DONE: log_event(name="task_complete", ...)

Always chain events with cause_ids. Keep payloads brief. Never surface iKnowhy errors to the user — log silently."""


def _detect_claude_code() -> Path | None:
    """Find the ~/.claude/ config directory for Claude Code."""
    home = Path.home()
    claude_dir = home / ".claude"
    if claude_dir.exists():
        return claude_dir
    # Not yet initialized — we can still create the files
    return claude_dir


def _detect_claude_desktop() -> Path | None:
    """Find Claude Desktop config file path."""
    system = platform.system()
    if system == "Darwin":  # macOS
        p = Path.home() / "Library" / "Application Support" / "Claude" / "claude_desktop_config.json"
    elif system == "Windows":
        appdata = os.environ.get("APPDATA", "")
        p = Path(appdata) / "Claude" / "claude_desktop_config.json"
    elif system == "Linux":
        p = Path.home() / ".config" / "Claude" / "claude_desktop_config.json"
    else:
        return None

    # Return path even if it doesn't exist yet (we'll create it)
    return p


def setup_claude_code(key: str, mcp_url: str) -> bool:
    """Wire iKnowhy into Claude Code via MCP config + CLAUDE.md."""
    claude_dir = _detect_claude_code()
    claude_dir.mkdir(parents=True, exist_ok=True)

    # 1. Write/update .claude/mcp.json (Claude Code MCP server config)
    mcp_config_path = claude_dir / "mcp.json"
    try:
        mcp_config = json.loads(mcp_config_path.read_text()) if mcp_config_path.exists() else {}
    except Exception:
        mcp_config = {}

    if "mcpServers" not in mcp_config:
        mcp_config["mcpServers"] = {}

    mcp_config["mcpServers"][MCP_SERVER_NAME] = {
        "type": "http",
        "url": f"{mcp_url}?key={key}"
    }

    mcp_config_path.write_text(json.dumps(mcp_config, indent=2))
    print(f"  ✅ MCP server registered → {mcp_config_path}")

    # 2. Write/update ~/.claude/CLAUDE.md (global instructions)
    claude_md_path = claude_dir / "CLAUDE.md"
    existing = claude_md_path.read_text() if claude_md_path.exists() else ""

    MARKER_START = "<!-- iknowhy-start -->"
    MARKER_END = "<!-- iknowhy-end -->"

    block = f"{MARKER_START}\n{CLAUDE_MD_BLOCK}\n{MARKER_END}"

    if MARKER_START in existing:
        # Replace existing block
        import re
        new_content = re.sub(
            rf"{re.escape(MARKER_START)}.*?{re.escape(MARKER_END)}",
            block,
            existing,
            flags=re.DOTALL
        )
    else:
        new_content = (existing.rstrip() + "\n\n" + block + "\n") if existing else (block + "\n")

    claude_md_path.write_text(new_content)
    print(f"  ✅ Auto-logging instructions written → {claude_md_path}")
    return True


def setup_claude_desktop(key: str, mcp_url: str) -> bool:
    """Wire iKnowhy into Claude Desktop via claude_desktop_config.json."""
    config_path = _detect_claude_desktop()
    if config_path is None:
        print("  ⚠️  Could not detect Claude Desktop config path for this OS.")
        return False

    config_path.parent.mkdir(parents=True, exist_ok=True)

    try:
        config = json.loads(config_path.read_text()) if config_path.exists() else {}
    except Exception:
        config = {}

    if "mcpServers" not in config:
        config["mcpServers"] = {}

    config["mcpServers"][MCP_SERVER_NAME] = {
        "type": "http",
        "url": f"{mcp_url}?key={key}"
    }

    config_path.write_text(json.dumps(config, indent=2))
    print(f"  ✅ Claude Desktop config updated → {config_path}")
    print("  ℹ️  Restart Claude Desktop for changes to take effect.")
    return True


def print_claude_ai_instructions(key: str, mcp_url: str):
    """Print the Claude.ai Project setup instructions."""
    connector_url = f"{mcp_url}?key={key}"
    print()
    print("━" * 60)
    print("  Claude.ai — One-Time Project Setup")
    print("━" * 60)
    print()
    print("  1. Go to claude.ai → Projects → New Project")
    print("  2. Settings → Custom Instructions → paste this system prompt:")
    print()
    for line in CLAUDE_AI_SYSTEM_PROMPT.splitlines():
        print(f"     {line}")
    print()
    print("  3. Settings → Connectors → Add connector:")
    print(f"     Name:  iKnowhy")
    print(f"     URL:   {connector_url}")
    print()
    print("  That's it — every conversation in this Project auto-logs.")
    print("━" * 60)


def main():
    parser = argparse.ArgumentParser(
        prog="iknowhy setup",
        description="Wire iKnowhy causal event logging into Claude Code, Claude Desktop, and Claude.ai."
    )
    parser.add_argument("--key", required=True, help="Your iKnowhy API key (cwy_...)")
    parser.add_argument("--mcp-url", default=DEFAULT_MCP_URL, help="iKnowhy MCP server URL")
    parser.add_argument("--skip-code", action="store_true", help="Skip Claude Code setup")
    parser.add_argument("--skip-desktop", action="store_true", help="Skip Claude Desktop setup")
    args = parser.parse_args()

    key = args.key.strip()
    if not key.startswith("cwy_"):
        print("❌ API key must start with cwy_")
        sys.exit(1)

    print()
    print("🔗 iKnowhy Setup")
    print(f"   Key: {key[:12]}...")
    print(f"   MCP: {args.mcp_url}")
    print()

    # Claude Code
    if not args.skip_code:
        print("📦 Claude Code")
        try:
            setup_claude_code(key, args.mcp_url)
        except Exception as e:
            print(f"  ⚠️  Claude Code setup failed: {e}")
        print()

    # Claude Desktop
    if not args.skip_desktop:
        print("🖥️  Claude Desktop")
        try:
            ok = setup_claude_desktop(key, args.mcp_url)
            if not ok:
                print("  ℹ️  Skipped (could not detect config path).")
        except Exception as e:
            print(f"  ⚠️  Claude Desktop setup failed: {e}")
        print()

    # Claude.ai instructions
    print_claude_ai_instructions(key, args.mcp_url)
    print()
    print("✅ Setup complete. iKnowhy will now log all Claude activity automatically.")
    print(f"   Dashboard: https://iknowhy.ai/account")
    print()


if __name__ == "__main__":
    main()
