"""
Directory tree building utilities.
"""

from pathlib import Path
from typing import Any

from loguru import logger

from skene_growth.codebase.filters import DEFAULT_EXCLUDE_FOLDERS


def build_directory_tree(
    folder_path: str | Path,
    exclude_folders: list[str] | None = None,
) -> list[dict[str, Any]]:
    """
    Generate JSON structure of files and folders iteratively.

    This function creates a hierarchical representation of a directory structure
    where each entry is a dictionary with 'name', 'type', and optionally 'children'
    for directories.

    Args:
        folder_path: Root directory path to build tree from
        exclude_folders: Additional folder names to exclude (merged with defaults)

    Returns:
        List of dictionaries representing the directory tree structure.
        Each dictionary has the format:
        - For files: {"name": str, "type": "file"}
        - For directories: {"name": str, "type": "directory", "children": List}

    Example:
        tree = build_directory_tree("/path/to/repo")
        # Returns:
        # [
        #     {"name": "src", "type": "directory", "children": [...]},
        #     {"name": "README.md", "type": "file"},
        # ]
    """
    # Merge provided excludes with defaults
    if exclude_folders is None:
        exclude_folders = []

    all_excludes = set(DEFAULT_EXCLUDE_FOLDERS + exclude_folders)

    def _build_tree_iterative(root_path: Path) -> list[dict[str, Any]]:
        """
        Internal iterative function to build the tree structure.
        Uses a stack-based approach to avoid deep recursion.

        Args:
            root_path: Root path to process

        Returns:
            List of items (files and directories) at the root level
        """
        if not root_path.is_dir():
            return []

        # Root container for the result
        root_items: list[dict[str, Any]] = []

        # Stack entries: (current_path, parent_children_list)
        # We'll process directories level by level
        stack: list[tuple[Path, list[dict[str, Any]]]] = [(root_path, root_items)]

        while stack:
            current_path, parent_list = stack.pop()

            try:
                # Get entries as an iterator to avoid loading all at once
                entries = list(current_path.iterdir())

                # Sort for consistent output (dirs first, then alphabetically)
                entries.sort(key=lambda x: (not x.is_dir(), x.name.lower()))

                for entry in entries:
                    # Skip excluded directories
                    if entry.name in all_excludes:
                        continue

                    if entry.is_dir():
                        # Create directory item with empty children list
                        children: list[dict[str, Any]] = []
                        item: dict[str, Any] = {
                            "name": entry.name,
                            "type": "directory",
                            "children": children,
                        }
                        parent_list.append(item)
                        # Add to stack to process this directory's contents
                        stack.append((entry, children))
                    else:
                        # Create file item
                        item = {"name": entry.name, "type": "file"}
                        parent_list.append(item)

            except PermissionError:
                logger.warning(f"Permission denied accessing: {current_path}")
            except Exception as e:
                logger.error(f"Error processing directory {current_path}: {e}")

        return root_items

    folder_path = Path(folder_path) if isinstance(folder_path, str) else folder_path
    logger.info(f"Building directory tree for: {folder_path}")
    tree = _build_tree_iterative(folder_path)
    logger.debug(f"Built directory tree with {len(tree)} top-level items")
    return tree
