"""
Template tags for Django Lotus Extras.

Provides additional functionality for blog templates including
reading time estimation, previous/next article navigation,
CTA retrieval, and popular articles widgets.
"""
from django import template

from ..conf import django_blog_plus_settings

register = template.Library()


@register.simple_tag
def get_adjacent_articles(article):
    """
    Get previous and next articles based on publish date.
    Returns a dict with 'previous' and 'next' keys.
    """
    try:
        from lotus.models import Article
        from lotus.choices import STATUS_PUBLISHED

        language = django_blog_plus_settings.get_language_code()

        # Get previous article (older, published before this one)
        previous = Article.objects.filter(
            language=language,
            status=STATUS_PUBLISHED,
            publish_date__lt=article.publish_date,
        ).order_by('-publish_date', '-publish_time').first()

        # If no article with earlier date, check same date but earlier time
        if not previous:
            previous = Article.objects.filter(
                language=language,
                status=STATUS_PUBLISHED,
                publish_date=article.publish_date,
                publish_time__lt=article.publish_time,
            ).exclude(pk=article.pk).order_by('-publish_time').first()

        # Get next article (newer, published after this one)
        next_article = Article.objects.filter(
            language=language,
            status=STATUS_PUBLISHED,
            publish_date__gt=article.publish_date,
        ).order_by('publish_date', 'publish_time').first()

        # If no article with later date, check same date but later time
        if not next_article:
            next_article = Article.objects.filter(
                language=language,
                status=STATUS_PUBLISHED,
                publish_date=article.publish_date,
                publish_time__gt=article.publish_time,
            ).exclude(pk=article.pk).order_by('publish_time').first()

        return {
            'previous': previous,
            'next': next_article,
        }
    except Exception:
        return {'previous': None, 'next': None}


@register.simple_tag
def reading_time(content):
    """
    Estimate reading time for given content.
    Returns the number of minutes (rounded up).
    Assumes average reading speed of 200 words per minute.
    """
    if not content:
        return 1

    # Strip HTML tags if present
    import re
    text = re.sub(r'<[^>]+>', '', str(content))

    # Count words
    words = len(text.split())

    # Calculate reading time (minimum 1 minute)
    minutes = max(1, round(words / 200))

    return minutes


@register.filter
def reading_time_filter(content):
    """
    Filter version of reading_time for use in templates.
    """
    return reading_time(content)


@register.simple_tag
def get_article_cover_style(article_id):
    """
    Get the cover style for an article.
    Returns a dict with 'background_color' key.
    """
    try:
        from ..models import ArticleCoverStyle
        style = ArticleCoverStyle.objects.get(article_id=article_id)
        return {
            'background_color': style.get_background_color(),
        }
    except ArticleCoverStyle.DoesNotExist:
        return {
            'background_color': django_blog_plus_settings.DEFAULT_COVER_BG_COLOR,
        }
    except Exception:
        return {
            'background_color': django_blog_plus_settings.DEFAULT_COVER_BG_COLOR,
        }


@register.filter
def article_cover_bg(article):
    """
    Filter to get the background color for an article's cover.
    Usage: {{ article|article_cover_bg }}
    """
    try:
        from ..models import ArticleCoverStyle
        style = ArticleCoverStyle.objects.get(article_id=article.id)
        return style.get_background_color()
    except Exception:
        return django_blog_plus_settings.DEFAULT_COVER_BG_COLOR


@register.filter
def demote_headings(content):
    """
    Convert H1 tags to H2 in article content for SEO.
    There should only be one H1 per page (the article title).
    This filter demotes any H1 tags in the content to H2.
    Usage: {{ article.content|demote_headings|safe }}
    """
    import re
    if not content:
        return content

    content = str(content)
    # Replace opening h1 tags with h2
    content = re.sub(r'<h1(\s[^>]*)?>', r'<h2\1>', content, flags=re.IGNORECASE)
    # Replace closing h1 tags with h2
    content = re.sub(r'</h1>', r'</h2>', content, flags=re.IGNORECASE)

    return content


@register.filter
def unescape_html(content):
    """
    Decode HTML entities in content.
    Converts &amp; to &, &rsquo; to ', etc.
    Usage: {{ article.introduction|striptags|unescape_html|truncatewords:25 }}
    """
    import html
    if not content:
        return content

    return html.unescape(str(content))


@register.simple_tag
def get_article_cta(article_id):
    """
    Get the Call to Action assigned to an article.
    Returns the BlogCallToAction object if assigned and active, None otherwise.

    Usage:
        {% get_article_cta article.id as cta %}
        {% if cta %}
            <div class="cta">{{ cta.title }}</div>
        {% endif %}
    """
    try:
        from ..models import ArticleCallToAction
        assignment = ArticleCallToAction.objects.select_related('cta').get(article_id=article_id)
        if assignment.cta.is_active:
            return assignment.cta
        return None
    except ArticleCallToAction.DoesNotExist:
        return None
    except Exception:
        return None


@register.simple_tag
def get_popular_articles(count=5):
    """
    Get the most popular articles based on view count.
    Returns a list of ArticleViewCount objects with their associated articles.

    Usage:
        {% get_popular_articles 5 as popular %}
        {% for item in popular %}
            {{ item.article.title }} - {{ item.view_count }} views
        {% endfor %}
    """
    try:
        from ..models import ArticleViewCount
        from lotus.models import Article
        from lotus.choices import STATUS_PUBLISHED

        language = django_blog_plus_settings.get_language_code()

        # Get top view counts
        top_views = ArticleViewCount.objects.order_by('-view_count')[:count * 2]

        # Fetch and attach the actual articles
        result = []
        for view_count in top_views:
            try:
                article = Article.objects.get(
                    id=view_count.article_id,
                    language=language,
                    status=STATUS_PUBLISHED
                )
                view_count.article = article
                result.append(view_count)
                if len(result) >= count:
                    break
            except Article.DoesNotExist:
                continue

        return result
    except Exception:
        return []


@register.simple_tag
def increment_article_view(article_id):
    """
    Increment the view count for an article.
    Returns empty string (for use in templates without output).

    Usage:
        {% increment_article_view article.id %}
    """
    try:
        from ..models import ArticleViewCount
        ArticleViewCount.increment_view(article_id)
    except Exception:
        pass
    return ''
