# django_spellbook/management/commands/processing/navigation.py

import logging
from typing import List, Dict, Tuple
from pathlib import Path
from collections import defaultdict

from django_spellbook.management.commands.processing.file_processor import ProcessedFile
from django_spellbook.management.commands.processing.generator_utils import get_clean_url

logger = logging.getLogger(__name__)


class NavigationBuilder:
    """
    Builds prev/next navigation links for processed markdown files.

    Navigation rules:
    1. Files are grouped by content_app AND parent directory
    2. Within each group, files are sorted alphabetically
    3. index.md is treated as first file (sorted as '00-index.md')
    4. Frontmatter overrides (prev/next in YAML) take precedence
    5. Navigation respects app and directory boundaries
    """

    @staticmethod
    def build_navigation(processed_files: List[ProcessedFile], content_app: str) -> None:
        """
        Build navigation links for all processed files.

        Mutates ProcessedFile.context objects in-place to set prev_page and next_page.

        Args:
            processed_files: List of processed markdown files
            content_app: Name of the content app (used for namespaced URLs)
        """
        if not processed_files:
            logger.debug("No processed files to build navigation for")
            return

        # Group files by parent directory
        groups = NavigationBuilder._group_files(processed_files)

        # Build navigation for each group independently
        for directory, files in groups.items():
            logger.debug(f"Building navigation for {len(files)} files in {content_app}:{directory}")
            NavigationBuilder._build_group_navigation(files, content_app)

    @staticmethod
    def _group_files(processed_files: List[ProcessedFile]) -> Dict[str, List[ProcessedFile]]:
        """
        Group files by parent directory.

        Args:
            processed_files: List of processed markdown files

        Returns:
            Dictionary mapping directory to list of files
        """
        groups = defaultdict(list)

        for pf in processed_files:
            # Get parent directory from original path
            parent_dir = Path(pf.original_path).parent

            # Group by directory
            groups[str(parent_dir)].append(pf)

        return groups

    @staticmethod
    def _build_group_navigation(files: List[ProcessedFile], app: str) -> None:
        """
        Build navigation for a group of files in the same app/directory.

        Args:
            files: List of files in the same app and directory
            app: Content app name
        """
        # Sort files alphabetically, with index.md treated as first
        sorted_files = sorted(files, key=NavigationBuilder._get_sort_key)

        # Build navigation chain
        for i, current_file in enumerate(sorted_files):
            # Check if frontmatter already specifies prev/next
            fm_prev = NavigationBuilder._get_frontmatter_override(current_file, 'prev')
            fm_next = NavigationBuilder._get_frontmatter_override(current_file, 'next')

            # Set prev_page (use frontmatter override if available)
            if fm_prev is not None:
                current_file.context.prev_page = fm_prev
                logger.debug(f"Using frontmatter prev for {current_file.relative_url}: {fm_prev}")
            elif i > 0:
                prev_file = sorted_files[i - 1]
                current_file.context.prev_page = NavigationBuilder._build_namespaced_url(prev_file, app)
                logger.debug(f"Auto prev for {current_file.relative_url}: {current_file.context.prev_page}")
            else:
                # First file in group, no previous
                current_file.context.prev_page = None

            # Set next_page (use frontmatter override if available)
            if fm_next is not None:
                current_file.context.next_page = fm_next
                logger.debug(f"Using frontmatter next for {current_file.relative_url}: {fm_next}")
            elif i < len(sorted_files) - 1:
                next_file = sorted_files[i + 1]
                current_file.context.next_page = NavigationBuilder._build_namespaced_url(next_file, app)
                logger.debug(f"Auto next for {current_file.relative_url}: {current_file.context.next_page}")
            else:
                # Last file in group, no next
                current_file.context.next_page = None

    @staticmethod
    def _get_sort_key(processed_file: ProcessedFile) -> str:
        """
        Generate sort key for a file, treating index.md as first.

        Args:
            processed_file: Processed markdown file

        Returns:
            String key for sorting (index.md becomes '000-index.md')
        """
        filename = Path(processed_file.original_path).name.lower()

        # Treat index.md as '000-index.md' for sorting (sorts before any number)
        if filename == 'index.md':
            return '000-index.md'
        else:
            return filename

    @staticmethod
    def _get_frontmatter_override(processed_file: ProcessedFile, field: str) -> str:
        """
        Get frontmatter override for prev or next field.

        Args:
            processed_file: Processed markdown file
            field: 'prev' or 'next'

        Returns:
            Frontmatter value if present, None otherwise
        """
        # The frontmatter parser should have already extracted prev/next
        # and stored them in the context
        return processed_file.context.get_safe_attr(field + '_page', None)

    @staticmethod
    def _build_namespaced_url(processed_file: ProcessedFile, app: str) -> str:
        """
        Generate namespaced URL for a processed file.

        Format: app_name:url_name (e.g., 'blog:01_intro', 'docs:setup')

        Args:
            processed_file: Processed markdown file
            app: Content app name

        Returns:
            Namespaced URL string
        """
        clean_url = get_clean_url(processed_file.relative_url)
        url_name = clean_url.replace('/', '_')

        return f"{app}:{url_name}"
