#!/usr/bin/env python3
# Copyright (c) 2026 PULSE Contributors. Proprietary. All rights reserved.
"""Brain scaffold initialization: consent, directory setup, migration."""

import json
import os
import sys
from datetime import datetime, timezone
from pathlib import Path

from pulse.core.paths_resolution import (
    _has_project_marker, _is_dev_mode, get_project_root, get_pulse_home,
)


class ConsentDeclined(Exception):
    """User declined PULSE data consent."""
    pass


class NoProjectRoot(Exception):
    """No valid project root found (no .git, .pulse.yaml, or PULSE_OS.md)."""
    pass

# === User brain initialization ===

BRAIN_SCAFFOLD = {
    "dirs": [
        "Lessons", "Failures", "Patterns", "Evidence",
        "Evidence/Sessions", "Evidence/Metrics", "Evidence/Learnings",
        "Intents", "Decisions", "Anti_Patterns",
        "Semantic", "Private",
    ],
    "jsonl_files": [
        "Lessons/auto_lessons.jsonl",
        "Failures/auto_fails.jsonl",
        "Patterns/auto_patterns.jsonl",
    ],
    "json_files": {
        "Evidence/Sessions/current_session.json": "[]",
        "Decisions/auto_decisions.json": "{}",
        "Evidence/Metrics/growth_metrics.json": "{}",
    },
}

MINIMAL_ANTI_PATTERNS_JSON = "[]"


def _check_consent() -> bool:
    """Check for user consent. Returns True if consent given."""
    # 1. Env var override (CI/CD, Docker, scripted deploys)
    if os.environ.get("PULSE_CONSENT", "").lower() in ("yes", "1", "true"):
        return True

    # 2. Existing consent marker
    consent_file = get_pulse_home() / "consent.json"
    if consent_file.exists():
        try:
            data = json.loads(consent_file.read_text(encoding="utf-8"))
            if data.get("consent_given"):
                return True
        except (json.JSONDecodeError, OSError):
            pass

    # 3. Non-interactive terminal — cannot prompt
    if not sys.stdin.isatty():
        return False

    # 4. Interactive prompt
    print("\n  PULSE — Persistent Unified Learning & Synthesis Engine\n")
    print("  PULSE learns from your AI conversations to build persistent memory.")
    print("  All data is stored LOCALLY on your machine. Nothing leaves your device.")
    print("  You can revoke consent and delete data at any time with: pulse consent revoke\n")
    try:
        answer = input("  Continue? [Y/n] ").strip().lower()
    except (EOFError, KeyboardInterrupt):
        return False
    if answer and answer != "y":
        return False

    # 5. Save consent marker
    consent_file.parent.mkdir(parents=True, exist_ok=True)
    consent_file.write_text(json.dumps({
        "consent_given": True,
        "consent_date": datetime.now(timezone.utc).isoformat(),
        "version": "1.0",
    }, indent=2), encoding="utf-8")
    return True


def init_user_brain(force: bool = False):
    """Create per-project scaffold at ~/.pulse/projects/<hash>/.

    Args:
        force: If True, skip project marker check (used by 'pulse init').
    """
    from pulse.core.paths import get_project_dir, get_brain_dir, get_state_dir, get_root_dir
    if not force:
        root = get_project_root()
        if not _has_project_marker(root):
            raise NoProjectRoot(
                f"No project found at {root}.\n"
                "  PULSE creates a separate brain per project.\n"
                "  To initialize here, run: pulse init\n"
                "  Or navigate to a git repository first."
            )

    if not _check_consent():
        raise ConsentDeclined("PULSE consent not given. Set PULSE_CONSENT=yes or run interactively.")
    proj_dir = get_project_dir()
    brain_dir = proj_dir / "brain"
    state_dir = proj_dir / "state"

    if (brain_dir / "Lessons").exists():
        print(f"[PULSE] Brain already initialized at {proj_dir}")
        return

    print(f"[PULSE] Initializing brain at {proj_dir}")

    # Brain directories + files
    for d in BRAIN_SCAFFOLD["dirs"]:
        (brain_dir / d).mkdir(parents=True, exist_ok=True)
    for path in BRAIN_SCAFFOLD["jsonl_files"]:
        p = brain_dir / path
        if not p.exists():
            p.touch()
    for path, content in BRAIN_SCAFFOLD["json_files"].items():
        (brain_dir / path).write_text(content + "\n", encoding="utf-8")

    # State + task board
    state_dir.mkdir(parents=True, exist_ok=True)
    (state_dir / "agent_registry.json").write_text("{}\n", encoding="utf-8")
    (state_dir / "task_board.json").write_text("{}\n", encoding="utf-8")

    # Migrate existing users: move task_board from old location
    old_tb = proj_dir / "Prefrontal_Cortex" / "Action_Queue" / "task_board.json"
    if old_tb.exists():
        import shutil
        shutil.move(str(old_tb), str(state_dir / "task_board.json"))
        # Clean up empty old dirs
        old_aq = old_tb.parent
        old_pf = old_aq.parent
        if old_aq.exists() and not any(old_aq.iterdir()):
            old_aq.rmdir()
        if old_pf.exists() and not any(old_pf.iterdir()):
            old_pf.rmdir()
    # Clean up old governance scaffold (no longer needed)
    old_cc = proj_dir / "Corpus_Callosum"
    if old_cc.exists() and not _is_dev_mode():
        import shutil
        shutil.rmtree(str(old_cc), ignore_errors=True)

    # Anti-patterns
    ap_file = brain_dir / "Anti_Patterns" / "anti_patterns_active.json"
    ap_file.parent.mkdir(parents=True, exist_ok=True)
    if not ap_file.exists():
        ap_file.write_text(MINIMAL_ANTI_PATTERNS_JSON + "\n", encoding="utf-8")

    # Copy default brain_config.json to user project (customizable)
    user_config_dir = proj_dir / "config"
    user_config_dir.mkdir(parents=True, exist_ok=True)
    user_config = user_config_dir / "brain_config.json"
    if not user_config.exists():
        pkg_config = Path(__file__).resolve().parent.parent / "config" / "brain_config.json"
        if pkg_config.exists():
            import shutil
            shutil.copy2(pkg_config, user_config)

    # Auto-generate .env with BRAIN_KEY (zero manual setup)
    env_file = proj_dir / ".env"
    if not env_file.exists():
        import secrets
        brain_key = secrets.token_hex(32)
        api_token = secrets.token_hex(16)
        env_file.write_text(
            f"# PULSE auto-generated environment\n"
            f"PULSE_BRAIN_KEY={brain_key}\n"
            f"PULSE_API_TOKEN={api_token}\n",
            encoding="utf-8",
        )

    # User profile (uses UserProfile dataclass → ~/.pulse/profile.json)
    from pulse.core.user_profile import UserProfile
    profile = UserProfile.load()
    _detected = profile.detect_providers()
    profile.save()

    # Auto-generate hook configs for all supported AI tools
    from pulse.core.hook_generator import generate_hooks
    project_root = get_project_root()
    hook_results = generate_hooks(project_root)

    print(f"  Brain:      {brain_dir}")
    print(f"  State:      {state_dir}")
    print(f"  Task board: {state_dir / 'task_board.json'}")
    if _detected:
        print(f"  Providers:  {', '.join(_detected)}")
    else:
        print("\n  No API keys detected. Set one or more to get started:")
        print("    export ANTHROPIC_API_KEY=sk-...")
        print("    export GEMINI_API_KEY=AI...")
        print("    export OPENAI_API_KEY=sk-...")
        print("  Or install Ollama for local models: https://ollama.com")
    print(f"  Config:     {proj_dir / 'config' / 'brain_config.json'}")

    # Show hook generation results
    gen_count = len(hook_results["generated"]) + len(hook_results.get("merged", []))
    if gen_count:
        print(f"\n  Hooks ({gen_count} configured):")
        for h in hook_results["generated"]:
            print(f"    + {h}")
        for h in hook_results.get("merged", []):
            print(f"    * {h}")
    if hook_results["skipped"]:
        for s in hook_results["skipped"]:
            print(f"    ~ {s}")

    # Show detected tools
    active = [k for k, v in hook_results["tools"].items() if v]
    if active:
        print(f"  CLI tools:  {', '.join(active)} detected in PATH")

    print(f"  License:    Run 'pulse activate <KEY>' to activate your subscription")
    print("\n[PULSE] Done. Run `pulse status` to verify.")


if __name__ == "__main__":
    print(f"Dev mode: {_is_dev_mode()}")
    print(f"Brain dir: {get_brain_dir()}")
    print(f"State dir: {get_state_dir()}")
    print(f"Root dir: {get_root_dir()}")
