"""
Admin extensions for Django Lotus Extras.

Provides admin interfaces for:
- ArticleCoverStyle - Custom cover backgrounds
- BlogCallToAction - Reusable CTA blocks
- ArticleCallToAction - Article-CTA assignments
- ExtendedArticleAdmin - Extended Lotus Article admin with CTA selector
"""

import logging

import requests
from django import forms
from django.contrib import admin, messages
from django.utils import timezone
from django.utils.html import format_html

from .conf import django_blog_plus_settings
from .models import (
    ArticleCallToAction,
    ArticleCoverStyle,
    ArticleViewCount,
    BlogCallToAction,
)

logger = logging.getLogger(__name__)


# Try to import CKEditor widget (optional dependency)
try:
    from ckeditor_uploader.widgets import CKEditorUploadingWidget
    CKEDITOR_AVAILABLE = True
except ImportError:
    CKEDITOR_AVAILABLE = False


# Try to import Lotus admin classes
try:
    from lotus.admin.article import ArticleAdmin as LotusArticleAdmin
    from lotus.forms import ArticleAdminForm as LotusArticleAdminForm
    from lotus.models import Article as LotusArticle
    LOTUS_AVAILABLE = True
except ImportError:
    LOTUS_AVAILABLE = False
    LotusArticleAdmin = None
    LotusArticleAdminForm = None
    LotusArticle = None


def send_article_published_webhook(article):
    """
    Send webhook notification when an article is published.
    Returns True if webhook was sent successfully, False otherwise.
    """
    webhook_url = django_blog_plus_settings.get_article_published_webhook_url()
    if not webhook_url:
        return False

    try:
        publish_dt = article.publish_datetime()
        authors = article.get_authors()
        categories = article.get_categories()

        webhook_payload = {
            'event_type': 'article_published',
            'article': {
                'id': article.id,
                'title': article.title,
                'slug': article.slug,
                'url': article.get_absolute_url(),
                'admin_url': f'/admin/lotus/article/{article.id}/change/',
                'publish_datetime': publish_dt.isoformat() if publish_dt else None,
                'scheduled_publish_datetime': publish_dt.isoformat() if publish_dt else None,
                'seo_title': article.seo_title or '',
                'lead': article.lead or '',
                'introduction': article.introduction or '',
            },
            'authors': [
                {
                    'id': author.id,
                    'name': author.get_full_name(),
                    'email': author.email,
                }
                for author in authors
            ],
            'categories': [
                {
                    'id': cat.id,
                    'title': cat.title,
                    'slug': cat.slug,
                }
                for cat in categories
            ],
            'timestamp': timezone.now().isoformat(),
        }

        response = requests.post(
            webhook_url,
            json=webhook_payload,
            timeout=10
        )
        response.raise_for_status()
        logger.info(f"[ARTICLE PUBLISHED] Webhook notification sent for article #{article.id}")
        return True
    except Exception as e:
        logger.error(f"[ARTICLE PUBLISHED] Failed to send webhook for article #{article.id}: {e}")
        return False


@admin.register(ArticleCoverStyle)
class ArticleCoverStyleAdmin(admin.ModelAdmin):
    """Admin interface for managing article cover background colors"""
    list_display = ('article_id', 'get_article_title', 'background_color', 'color_preview', 'custom_color', 'updated_at')
    list_filter = ('background_color',)
    search_fields = ('article_id',)
    readonly_fields = ('created_at', 'updated_at', 'color_preview')

    fieldsets = (
        ('Article', {
            'fields': ('article_id',),
            'description': 'Enter the ID of the Lotus Article (found in the article admin URL).',
        }),
        ('Background Color', {
            'fields': ('background_color', 'custom_color', 'color_preview'),
            'description': 'Choose a preset color or enter a custom hex color (e.g., #FF5733).',
        }),
        ('Timestamps', {
            'fields': ('created_at', 'updated_at'),
            'classes': ('collapse',),
        }),
    )

    def get_article_title(self, obj):
        """Try to get the article title from Lotus"""
        if not LOTUS_AVAILABLE:
            return f'Article #{obj.article_id}'
        try:
            article = LotusArticle.objects.get(id=obj.article_id)
            return article.title[:50] + '...' if len(article.title) > 50 else article.title
        except Exception:
            return f'Article #{obj.article_id}'
    get_article_title.short_description = 'Article Title'

    def color_preview(self, obj):
        """Show a visual preview of the background color"""
        color = obj.get_background_color()
        return format_html(
            '<div style="width: 60px; height: 30px; background-color: {}; border: 1px solid #ccc; border-radius: 4px;"></div>',
            color
        )
    color_preview.short_description = 'Preview'


class BlogCallToActionForm(forms.ModelForm):
    """Custom form for BlogCallToAction with optional CKEditor widget"""
    
    class Meta:
        model = BlogCallToAction
        fields = '__all__'
    
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # Use CKEditor if available
        if CKEDITOR_AVAILABLE:
            self.fields['text'].widget = CKEditorUploadingWidget(config_name='lotus')


@admin.register(BlogCallToAction)
class BlogCallToActionAdmin(admin.ModelAdmin):
    """Admin interface for managing reusable CTAs"""
    form = BlogCallToActionForm
    list_display = ('title', 'is_active', 'image_preview', 'button_text', 'usage_count', 'updated_at')
    list_filter = ('is_active',)
    search_fields = ('title', 'text', 'button_text')
    readonly_fields = ('created_at', 'updated_at', 'image_preview_large')
    list_editable = ('is_active',)

    fieldsets = (
        ('Content', {
            'fields': ('title', 'text'),
            'description': 'The main content of the CTA block.',
        }),
        ('Image', {
            'fields': ('image', 'image_preview_large'),
        }),
        ('Button (Optional)', {
            'fields': ('button_text', 'button_url'),
            'description': 'Optional button to display at the bottom of the CTA.',
        }),
        ('Status', {
            'fields': ('is_active',),
            'description': 'Inactive CTAs will not be displayed even if assigned to articles.',
        }),
        ('Timestamps', {
            'fields': ('created_at', 'updated_at'),
            'classes': ('collapse',),
        }),
    )

    def image_preview(self, obj):
        """Show a small thumbnail in the list view"""
        if obj.image:
            return format_html(
                '<img src="{}" style="max-width: 60px; max-height: 40px; border-radius: 4px;"/>',
                obj.image.url
            )
        return '-'
    image_preview.short_description = 'Image'

    def image_preview_large(self, obj):
        """Show a larger preview in the detail view"""
        if obj.image:
            return format_html(
                '<img src="{}" style="max-width: 300px; max-height: 200px; border-radius: 8px;"/>',
                obj.image.url
            )
        return 'No image uploaded'
    image_preview_large.short_description = 'Preview'

    def usage_count(self, obj):
        """Show how many articles use this CTA"""
        count = obj.article_assignments.count()
        return f'{count} article{"s" if count != 1 else ""}'
    usage_count.short_description = 'Usage'


@admin.register(ArticleCallToAction)
class ArticleCallToActionAdmin(admin.ModelAdmin):
    """Admin interface for assigning CTAs to articles"""
    list_display = ('article_id', 'get_article_title', 'cta', 'updated_at')
    list_filter = ('cta',)
    search_fields = ('article_id',)
    readonly_fields = ('created_at', 'updated_at')
    autocomplete_fields = ('cta',)

    fieldsets = (
        ('Article', {
            'fields': ('article_id',),
            'description': 'Enter the ID of the Lotus Article (found in the article admin URL).',
        }),
        ('CTA Assignment', {
            'fields': ('cta',),
            'description': 'Select which CTA to display at the end of this article.',
        }),
        ('Timestamps', {
            'fields': ('created_at', 'updated_at'),
            'classes': ('collapse',),
        }),
    )

    def get_article_title(self, obj):
        """Try to get the article title from Lotus"""
        if not LOTUS_AVAILABLE:
            return f'Article #{obj.article_id}'
        try:
            article = LotusArticle.objects.get(id=obj.article_id)
            return article.title[:50] + '...' if len(article.title) > 50 else article.title
        except Exception:
            return f'Article #{obj.article_id}'
    get_article_title.short_description = 'Article Title'


@admin.register(ArticleViewCount)
class ArticleViewCountAdmin(admin.ModelAdmin):
    """Admin interface for viewing article view counts"""
    list_display = ('article_id', 'get_article_title', 'view_count', 'last_viewed', 'created_at')
    list_filter = ('last_viewed',)
    search_fields = ('article_id',)
    readonly_fields = ('article_id', 'view_count', 'last_viewed', 'created_at')
    ordering = ('-view_count',)

    def get_article_title(self, obj):
        """Try to get the article title from Lotus"""
        if not LOTUS_AVAILABLE:
            return f'Article #{obj.article_id}'
        try:
            article = LotusArticle.objects.get(id=obj.article_id)
            return article.title[:50] + '...' if len(article.title) > 50 else article.title
        except Exception:
            return f'Article #{obj.article_id}'
    get_article_title.short_description = 'Article Title'

    def has_add_permission(self, request):
        """View counts are created automatically"""
        return False


# =============================================================================
# Extended Lotus ArticleAdmin with CTA selector
# =============================================================================

if LOTUS_AVAILABLE and LotusArticleAdmin is not None:
    
    class ExtendedArticleForm(LotusArticleAdminForm):
        """Extended form for Lotus Article with CTA selector."""
        cta = forms.ModelChoiceField(
            queryset=BlogCallToAction.objects.filter(is_active=True),
            required=False,
            empty_label="(No CTA)",
            help_text="Select a Call to Action to display at the end of this article."
        )

        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            # Load existing CTA assignment if article exists
            if self.instance and self.instance.pk:
                try:
                    assignment = ArticleCallToAction.objects.get(article_id=self.instance.pk)
                    self.fields['cta'].initial = assignment.cta
                except ArticleCallToAction.DoesNotExist:
                    pass

    class ExtendedArticleAdmin(LotusArticleAdmin):
        """Extended Lotus ArticleAdmin with CTA selector"""
        form = ExtendedArticleForm
        list_display = ('title', 'is_published', 'publish_datetime', 'language_name', 'is_original',
                        'pinned', 'featured', 'last_update', 'private', 'view_live_link')
        actions = ['publish_scheduled_articles_action']

        def get_readonly_fields(self, request, obj=None):
            """Add scheduled_publish_info to readonly fields"""
            readonly = list(super().get_readonly_fields(request, obj) or [])
            readonly.append('scheduled_publish_info')
            return readonly

        def publish_scheduled_articles_action(self, request, queryset):
            """Admin action to manually publish scheduled articles"""
            from lotus.choices import STATUS_PUBLISHED

            now = timezone.now()
            published_count = 0
            webhook_sent_count = 0

            for article in queryset:
                if article.status == STATUS_PUBLISHED:
                    continue

                try:
                    publish_dt = article.publish_datetime()
                    if publish_dt and publish_dt <= now:
                        article.status = STATUS_PUBLISHED
                        article.save(update_fields=['status'])
                        published_count += 1

                        # Send webhook notification
                        if send_article_published_webhook(article):
                            webhook_sent_count += 1
                except Exception as e:
                    self.message_user(
                        request,
                        f'Error publishing article #{article.id}: {e}',
                        level=messages.ERROR
                    )

            if published_count > 0:
                msg = f'Successfully published {published_count} article(s).'
                if webhook_sent_count > 0:
                    msg += f' Webhook notifications sent: {webhook_sent_count}.'
                self.message_user(
                    request,
                    msg,
                    level=messages.SUCCESS
                )
            else:
                self.message_user(
                    request,
                    'No articles were ready to publish. Check that articles have publish_datetime <= now() and status != published.',
                    level=messages.INFO
                )
        publish_scheduled_articles_action.short_description = 'Publish selected scheduled articles (if time has passed)'

        def view_live_link(self, obj):
            """Show a link to view the live article"""
            url = obj.get_absolute_url()
            return format_html(
                '<a href="{}" target="_blank" style="white-space: nowrap;">View →</a>',
                url
            )
        view_live_link.short_description = 'Live'
        view_live_link.admin_order_field = 'slug'

        def scheduled_publish_info(self, obj):
            """Show scheduled publishing information for draft articles"""
            if not obj or not obj.pk:
                return '-'

            from lotus.choices import STATUS_PUBLISHED

            if obj.status == STATUS_PUBLISHED:
                return '-'

            try:
                publish_dt = obj.publish_datetime()
                if publish_dt:
                    now = timezone.now()
                    if publish_dt > now:
                        return format_html(
                            '<span style="color: #5DBEA3; font-weight: 600;">Will auto-publish at: {}</span>',
                            publish_dt.strftime('%Y-%m-%d %H:%M:%S')
                        )
                    else:
                        return format_html(
                            '<span style="color: #dc3545; font-weight: 600;">⚠️ Scheduled time passed - run '
                            'publish_scheduled_articles command</span>'
                        )
            except Exception:
                pass

            return '-'
        scheduled_publish_info.short_description = 'Scheduled Publishing'
        scheduled_publish_info.help_text = 'For draft articles with future publish dates, shows when they will automatically publish'

        def get_fieldsets(self, request, obj=None):
            """Add CTA fieldset to the end"""
            fieldsets = super().get_fieldsets(request, obj)
            # Convert to list if it's a tuple
            fieldsets = list(fieldsets)

            # Add scheduled publishing info if article exists and is draft
            if obj and obj.pk:
                from lotus.choices import STATUS_PUBLISHED
                if obj.status != STATUS_PUBLISHED:
                    # Insert scheduled publishing info before CTA
                    fieldsets.insert(-1, (
                        'Scheduled Publishing', {
                            'fields': ('scheduled_publish_info',),
                            'description': 'Draft articles with future publish dates will automatically publish when the '
                            'scheduled time arrives.',
                            'classes': ('collapse',),
                        }
                    ))

            # Add CTA fieldset
            fieldsets.append(
                ('Call to Action', {
                    'fields': ('cta',),
                    'description': 'Optionally assign a CTA block to display at the end of this article.',
                })
            )
            return fieldsets

        def save_model(self, request, obj, form, change):
            """Save the article and handle CTA assignment"""
            super().save_model(request, obj, form, change)

            # Handle CTA assignment after article is saved
            cta = form.cleaned_data.get('cta')
            if cta:
                # Create or update assignment
                ArticleCallToAction.objects.update_or_create(
                    article_id=obj.pk,
                    defaults={'cta': cta}
                )
            else:
                # Remove assignment if CTA cleared
                ArticleCallToAction.objects.filter(article_id=obj.pk).delete()

            # SEO Warning: Check for missing cover image alt text
            if obj.cover and not obj.cover_alt_text:
                messages.warning(
                    request,
                    '⚠️ SEO Tip: This article has a cover image but no alt text. '
                    'Adding descriptive alt text improves accessibility and search rankings.'
                )

    # Register the extended admin
    def register_extended_article_admin():
        """Register the extended article admin, unregistering the original if needed."""
        try:
            admin.site.unregister(LotusArticle)
        except admin.sites.NotRegistered:
            pass
        admin.site.register(LotusArticle, ExtendedArticleAdmin)
    
    # Auto-register when admin is loaded
    # Note: You can also call this manually in your project if needed
    register_extended_article_admin()
