from ..views import TOC
from typing import Dict
from django import template
from django.urls import reverse, NoReverseMatch
from django.core.exceptions import ImproperlyConfigured
from django.template.loader import render_to_string
from django.template import TemplateDoesNotExist

from django_spellbook.utils import remove_leading_dash
from django_spellbook.markdown.context import SpellbookContext

from .tag_utils import get_user_metadata_template, get_dev_metadata_template, get_current_app_index

register = template.Library()


@register.inclusion_tag('django_spellbook/tocs/sidebar_toc.html', takes_context=True)
def sidebar_toc(context) -> Dict:
    """
    Generate the table of contents for the sidebar layout.

    Args:
        context: The template context from the current view

    Returns:
        Dict containing the TOC data

    Raises:
        ImproperlyConfigured: If TOC is not found in the context
    """
    toc = context.get('toc')
    current_url = context.get('current_url')
    if toc is None:
        raise ImproperlyConfigured(
            "The 'toc' variable is required in the context for sidebar_toc tag"
        )
    return {'toc': toc, 'current_url': current_url}


@register.simple_tag(takes_context=True)
def show_metadata(context, display_type="for_user"):
    """
    Display metadata in a formatted way.
    
    Args:
        context: The template context
        display_type: Either 'for_user' or 'for_dev'
    
    Returns:
        Rendered HTML string
    """
    if display_type not in ['for_user', 'for_dev']:
        return f"Error: show_metadata tag requires 'for_user' or 'for_dev', got '{display_type}'"
    
    if context:
        # Get metadata from context
        metadata = context.get('metadata', {})
    else:
        metadata = {}
    
    # Get app index from context
    app_index = get_current_app_index(context)
    
    # Determine which template to use
    if display_type == 'for_user':
        template = get_user_metadata_template(app_index)
    else:  # display_type == 'for_dev'
        template = get_dev_metadata_template(app_index)
    
    # Create template context
    template_context = {
        'metadata': metadata
    }
    
    # Render the template
    try:
        return render_to_string(template, template_context)
    except TemplateDoesNotExist:
        return f"Error: Metadata template '{template}' not found"
    except Exception as e:
        return f"Error: Failed to render metadata template '{template}': {str(e)}"


@register.simple_tag
def spellbook_url(url_path: str) -> str:
    """
    Convert a TOC url path to a proper Django URL.

    Args:
        url_path (str): The URL path to convert

    Returns:
        str: The reversed URL if successful
        
    Exceptions:
        NoReverseMatch: If the URL path is not found

    """
    try:
        if not url_path:
            return '#'
        return reverse(url_path)
    except NoReverseMatch:
        return f"{url_path} xx Not Found"


@register.inclusion_tag('django_spellbook/data/styles.html')
def spellbook_styles():
    """
    Include the spellbook styles in the page with dynamic theme support.
    
    This tag generates CSS variables from Django settings and passes them
    to the template for inclusion before the static CSS files.
    """
    from django.conf import settings
    from django_spellbook.theme import generate_theme_css
    
    # Get theme configuration from settings
    theme_config = getattr(settings, 'SPELLBOOK_THEME', None)
    
    # Generate theme CSS variables
    # Always generate CSS (even with defaults) to ensure variables are available
    theme_css = generate_theme_css(theme_config)
    
    # Return context for the template
    return {
        'theme_css': theme_css
    }


@register.simple_tag
def dash_strip(string: str) -> str:
    """Strip the initial dashes from a string"""
    return remove_leading_dash(string)


@register.simple_tag(takes_context=True)
def page_header(context):
    """
    Display unified page header with title, author, and navigation.

    Includes:
    - Back to parent directory (if not at root)
    - Title
    - Author (if set)
    - Prev/Next navigation

    Args:
        context: The template context

    Returns:
        Rendered HTML string
    """
    if not context:
        return ""

    metadata = context.get('metadata', {})

    # Get parent directory info from context
    parent_dir_url = context.get('parent_directory_url')
    parent_dir_name = context.get('parent_directory_name', 'Directory')

    template_context = {
        'title': metadata.get('title'),
        'author': metadata.get('author'),
        'prev_page': metadata.get('prev_page'),
        'next_page': metadata.get('next_page'),
        'parent_dir_url': parent_dir_url,
        'parent_dir_name': parent_dir_name,
    }

    try:
        return render_to_string(
            'django_spellbook/components/page_header.html',
            template_context
        )
    except TemplateDoesNotExist:
        return "Error: Page header template not found"
    except Exception as e:
        return f"Error: Failed to render page header: {str(e)}"


@register.simple_tag(takes_context=True)
def page_metadata(context, display_type="for_user"):
    """
    Alias for show_metadata with clearer naming.
    Displays publication metadata (dates, tags, word count).

    Args:
        context: The template context
        display_type: Either 'for_user' or 'for_dev'

    Returns:
        Rendered HTML string
    """
    return show_metadata(context, display_type)
