"""
The Librarian: Scans the codebase and builds a knowledge map.
Gives agents instant context without reading every file.
"""

import os
import ast
from pathlib import Path


class LibrarianTool:
    """
    The Cartographer: Scans the codebase and builds a knowledge map.
    """
    def __init__(self, root_dir="."):
        self.root_dir = Path(root_dir)
        self.ignore_dirs = {'.git', '__pycache__', 'venv', 'env', 'node_modules', '.idea', 'dist', 'build', 'egg-info'}
        
    def _is_ignored(self, path):
        """Check if path should be ignored."""
        parts = path.parts
        for part in parts:
            if part in self.ignore_dirs or part.startswith('.') or 'egg-info' in part:
                return True
        return False

    def scan_codebase(self):
        """Walks the codebase and extracts structure."""
        print(f"🔭 Scanning codebase at {self.root_dir.absolute()}...")
        
        structure = []
        file_count = 0
        
        for root, dirs, files in os.walk(self.root_dir):
            # Modify dirs in-place to skip ignored directories
            dirs[:] = [d for d in dirs if d not in self.ignore_dirs and not d.startswith('.') and 'egg-info' not in d]
            
            for file in files:
                if file.endswith('.py'):
                    file_path = Path(root) / file
                    if self._is_ignored(file_path):
                        continue
                        
                    info = self._parse_python_file(file_path)
                    structure.append(info)
                    file_count += 1

        self._save_map(structure)
        print(f"✅ Learned {file_count} Python files. Knowledge updated.")
        print(f"📄 View: squadron/knowledge/CODEBASE_MAP.md")

    def _parse_python_file(self, path):
        """Extracts classes and functions from a Python file."""
        rel_path = path.relative_to(self.root_dir)
        summary = f"### 📄 `{rel_path}`\n"
        
        try:
            with open(path, "r", encoding="utf-8") as f:
                source = f.read()
                tree = ast.parse(source)
                
            # Get Module Docstring
            docstring = ast.get_docstring(tree)
            if docstring:
                first_line = docstring.strip().splitlines()[0]
                summary += f"_{first_line}_\n\n"
            
            # Get Classes (top-level only)
            for node in tree.body:
                if isinstance(node, ast.ClassDef):
                    class_doc = ast.get_docstring(node)
                    doc_hint = f" - _{class_doc.splitlines()[0]}_" if class_doc else ""
                    summary += f"- 📦 **Class**: `{node.name}`{doc_hint}\n"
                    
                    # Get Class methods (public only)
                    for item in node.body:
                        if isinstance(item, ast.FunctionDef) and not item.name.startswith('_'):
                            summary += f"  - `.{item.name}()`\n"
                            
                elif isinstance(node, ast.FunctionDef):
                    # Top-level functions
                    func_doc = ast.get_docstring(node)
                    doc_hint = f" - _{func_doc.splitlines()[0]}_" if func_doc else ""
                    summary += f"- ⚡ **Function**: `{node.name}()`{doc_hint}\n"

        except Exception as e:
            summary += f"_(Parse error: {e})_\n"
            
        return summary + "\n"

    def _save_map(self, structure):
        """Saves the map to knowledge/CODEBASE_MAP.md"""
        knowledge_dir = self.root_dir / "squadron" / "knowledge"
        knowledge_dir.mkdir(parents=True, exist_ok=True)
        
        target_file = knowledge_dir / "CODEBASE_MAP.md"
        
        content = "# 🗺️ Codebase Map\n\n"
        content += "> **Auto-generated by Squadron Librarian**\n"
        content += "> Run `squadron learn` to refresh.\n\n"
        content += "---\n\n"
        content += "".join(structure)
        
        with open(target_file, "w", encoding="utf-8") as f:
            f.write(content)
