"""
Stop Hook

Called when Claude finishes responding. Triggers triage to extract
learnings from the completed task chunk.
"""

import os
import sys
import asyncio
from pathlib import Path
from typing import Optional

# Skip if this is a CodeContext subprocess (prevents recursive hooks)
if os.environ.get("CODECONTEXT_SUBPROCESS") == "1":
    sys.exit(0)

# Add codecontext to path for imports (hooks/ is inside codecontext/)
sys.path.insert(0, str(Path(__file__).parent.parent))

from hooks.state import ChunkState, find_jsonl_for_session
from hooks.cleanup import cleanup_project_temp_files


def on_stop(event_data: dict) -> None:
    """
    Handle Stop event.

    Args:
        event_data: Event data from Claude Code containing:
            - session_id: Current session ID
            - reason: Why stopped (completed, error, interrupted, etc.)
            - transcript_path: Direct path to JSONL file (preferred)
    """
    reason = event_data.get("reason", "unknown")
    session_id = event_data.get("session_id", "unknown")
    transcript_path = event_data.get("transcript_path")

    # Get project path - env var (set by Claude) or cwd from stdin event
    cwd = os.environ.get("CLAUDE_PROJECT_DIR") or event_data.get("cwd", "")

    # Load chunk state - use session_id for precise lookup
    state = ChunkState.load(session_id=session_id, project_path=cwd)
    if not state:
        print("[CodeContext] No chunk state found, skipping triage")
        return

    # Get JSONL path - prefer transcript_path from event, then state, then search
    jsonl_path = transcript_path or state.jsonl_path
    if not jsonl_path:
        # Try to find it
        found = find_jsonl_for_session(
            state.session_id or session_id,
            state.project_path
        )
        if found:
            jsonl_path = str(found)

    if not jsonl_path or not Path(jsonl_path).exists():
        print(f"[CodeContext] JSONL not found, skipping triage")
        ChunkState.clear(session_id=state.session_id, project_path=state.project_path)
        return

    # Import here to avoid circular imports
    from hooks.jsonl_parser import extract_chunk_after_timestamp, chunk_to_transcript
    from memory_extractor import triage_and_store  # Now in codecontext

    # Extract chunk from JSONL
    chunk = extract_chunk_after_timestamp(
        jsonl_path=jsonl_path,
        start_timestamp=state.chunk_start_timestamp
    )

    if not chunk:
        print("[CodeContext] Empty chunk, skipping triage")
        ChunkState.clear(session_id=state.session_id, project_path=state.project_path)
        return

    # Format as transcript
    transcript = chunk_to_transcript(chunk, state.user_prompt)

    print(f"[CodeContext] Chunk complete ({len(chunk)} messages), triggering triage...")

    # Run triage (async but we wait for it in CLI mode)
    try:
        # Try async
        loop = asyncio.get_event_loop()
        if loop.is_running():
            # Schedule for later (non-blocking)
            asyncio.create_task(triage_and_store(transcript, state.user_prompt, state.project_path))
        else:
            # Run synchronously
            asyncio.run(triage_and_store(transcript, state.user_prompt, state.project_path))
    except RuntimeError:
        # No event loop, run sync
        asyncio.run(triage_and_store(transcript, state.user_prompt, state.project_path))

    # Clear state with session_id and project_path for precise deletion
    ChunkState.clear(session_id=state.session_id, project_path=state.project_path)
    print("[CodeContext] Triage complete, state cleared")

    # Cleanup temp files
    cleanup_project_temp_files(state.project_path)


def on_stop_sync(event_data: dict) -> None:
    """
    Synchronous version that doesn't wait for triage.
    Use this in hook contexts where you can't block.
    """
    reason = event_data.get("reason", "unknown")
    session_id = event_data.get("session_id", "unknown")
    transcript_path = event_data.get("transcript_path")

    # Get project path - env var (set by Claude) or cwd from stdin event
    cwd = os.environ.get("CLAUDE_PROJECT_DIR") or event_data.get("cwd", "")

    # Load chunk state - use session_id for precise lookup
    state = ChunkState.load(session_id=session_id, project_path=cwd)
    if not state:
        print("[CodeContext] No chunk state found, skipping triage")
        return

    # Get JSONL path - prefer transcript_path from event, then state, then search
    jsonl_path = transcript_path or state.jsonl_path
    if not jsonl_path:
        found = find_jsonl_for_session(
            state.session_id or session_id,
            state.project_path
        )
        if found:
            jsonl_path = str(found)

    if not jsonl_path or not Path(jsonl_path).exists():
        print(f"[CodeContext] JSONL not found, skipping triage")
        ChunkState.clear(session_id=state.session_id, project_path=state.project_path)
        return

    from hooks.jsonl_parser import extract_chunk_after_timestamp, chunk_to_transcript
    from memory_extractor import spawn_triage_background  # Now in codecontext

    # Extract chunk
    chunk = extract_chunk_after_timestamp(
        jsonl_path=jsonl_path,
        start_timestamp=state.chunk_start_timestamp
    )

    if not chunk:
        print("[CodeContext] Empty chunk, skipping triage")
        ChunkState.clear(session_id=state.session_id, project_path=state.project_path)
        return

    # Format transcript
    transcript = chunk_to_transcript(chunk, state.user_prompt)

    # Spawn background triage (non-blocking)
    spawn_triage_background(transcript, state.user_prompt, state.project_path)

    # Clear state immediately with session_id and project_path
    ChunkState.clear(session_id=state.session_id, project_path=state.project_path)
    print(f"[CodeContext] Chunk complete ({len(chunk)} messages), triage spawned in background")

    # Cleanup temp files
    cleanup_project_temp_files(state.project_path)


# Entry point - reads from stdin when called by Claude Code hooks
if __name__ == "__main__":
    import json

    try:
        # Claude Code passes event data via stdin as JSON
        input_data = sys.stdin.read()

        if input_data.strip():
            event = json.loads(input_data)

            # Map Claude Code's field names to our expected format
            # Stop provides: session_id, stop_reason, transcript_path, cwd
            # Note: CLAUDE_PROJECT_DIR is only in env var, not stdin (see docs/claude-hook-event-data.md)
            event_data = {
                "session_id": event.get("session_id", "unknown"),
                "reason": event.get("stop_reason", event.get("reason", "unknown")),
                "transcript_path": event.get("transcript_path"),
                "cwd": event.get("cwd", ""),
            }

            # Use sync version to not block Claude Code
            # Triage runs in background thread
            on_stop_sync(event_data)
        else:
            # No stdin - might be manual test
            print("[CodeContext] No event data received via stdin", file=sys.stderr)
            sys.exit(0)

    except json.JSONDecodeError as e:
        print(f"[CodeContext] JSON parse error: {e}", file=sys.stderr)
        sys.exit(1)
    except Exception as e:
        print(f"[CodeContext] Hook error: {e}", file=sys.stderr)
        # Exit 0 to not block Claude Code on errors
        sys.exit(0)
