"""
Management command to automatically publish scheduled blog articles.

This command checks for articles that have a scheduled publish_datetime
in the past but are still in draft status, and automatically publishes them.

When articles are published, a webhook notification is sent (if configured).

Run this command via cron every 5 minutes:
    */5 * * * * cd /path/to/project && python manage.py publish_scheduled_articles

Or run manually:
    python manage.py publish_scheduled_articles
    python manage.py publish_scheduled_articles --dry-run  # Preview without publishing
"""
import logging

import requests
from django.core.management.base import BaseCommand
from django.utils import timezone
from lotus.choices import STATUS_PUBLISHED
from lotus.models import Article

from django_blog_plus.conf import django_blog_plus_settings

logger = logging.getLogger(__name__)


class Command(BaseCommand):
    help = 'Automatically publish blog articles whose scheduled publish_datetime has arrived'

    def add_arguments(self, parser):
        parser.add_argument(
            '--dry-run',
            action='store_true',
            help='Preview articles that would be published without actually publishing them',
        )
        parser.add_argument(
            '--verbose',
            action='store_true',
            help='Show detailed information about each article processed',
        )

    def handle(self, *args, **options):
        dry_run = options['dry_run']
        verbose = options['verbose']

        language = django_blog_plus_settings.get_language_code()
        now = timezone.now()

        # Find articles that:
        # 1. Are in the correct language
        # 2. Are not already published (status != STATUS_PUBLISHED)
        # 3. Have a publish_datetime that is in the past or now
        all_articles = Article.objects.filter(language=language).exclude(status=STATUS_PUBLISHED)

        articles_to_publish = []
        for article in all_articles:
            try:
                publish_dt = article.publish_datetime()
                if publish_dt and publish_dt <= now:
                    articles_to_publish.append(article)
            except Exception as e:
                if verbose:
                    self.stdout.write(
                        self.style.WARNING(
                            f"  SKIP (error calculating publish_datetime): Article #{article.id} - {e}"
                        )
                    )
                continue

        if not articles_to_publish:
            self.stdout.write(
                self.style.SUCCESS('No articles ready to be published.')
            )
            return

        action = "Would publish" if dry_run else "Publishing"
        self.stdout.write(
            self.style.SUCCESS(f"{action} {len(articles_to_publish)} article(s)...")
        )

        published_count = 0
        failed_count = 0

        for article in articles_to_publish:
            try:
                publish_dt = article.publish_datetime()
                status_text = "draft" if article.status == 0 else f"status={article.status}"

                if verbose:
                    self.stdout.write(
                        f"  Article #{article.id}: '{article.title[:50]}...' "
                        f"(scheduled: {publish_dt}, current: {status_text})"
                    )

                if dry_run:
                    self.stdout.write(
                        self.style.SUCCESS(
                            f"    WOULD PUBLISH: Article #{article.id} - '{article.title}'"
                        )
                    )
                    published_count += 1
                else:
                    # Update status to published
                    article.status = STATUS_PUBLISHED
                    article.save(update_fields=['status'])

                    logger.info(
                        f"[SCHEDULED PUBLISH] Published article #{article.id} - '{article.title}' "
                        f"(scheduled for {publish_dt})"
                    )
                    self.stdout.write(
                        self.style.SUCCESS(
                            f"    PUBLISHED: Article #{article.id} - '{article.title}'"
                        )
                    )
                    published_count += 1

                    # Send webhook notification if configured
                    webhook_url = django_blog_plus_settings.get_article_published_webhook_url()
                    if webhook_url:
                        try:
                            # Get article details
                            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"[SCHEDULED PUBLISH] Webhook notification sent for article #{article.id}"
                            )
                            if verbose:
                                self.stdout.write(
                                    self.style.SUCCESS(
                                        "      Webhook sent successfully"
                                    )
                                )
                        except requests.Timeout:
                            logger.error(
                                f"[SCHEDULED PUBLISH] Webhook timeout for article #{article.id}"
                            )
                            if verbose:
                                self.stdout.write(
                                    self.style.WARNING(
                                        "      Webhook timeout"
                                    )
                                )
                        except requests.RequestException as e:
                            logger.error(
                                f"[SCHEDULED PUBLISH] Failed to send webhook for article #{article.id}: {e}"
                            )
                            if verbose:
                                self.stdout.write(
                                    self.style.WARNING(
                                        f"      Webhook failed: {e}"
                                    )
                                )
                        except Exception as e:
                            logger.error(
                                f"[SCHEDULED PUBLISH] Unexpected error sending webhook for article #{article.id}: {e}"
                            )
                            if verbose:
                                self.stdout.write(
                                    self.style.WARNING(
                                        f"      Webhook error: {e}"
                                    )
                                )

            except Exception as e:
                failed_count += 1
                logger.error(
                    f"[SCHEDULED PUBLISH] Failed to publish article #{article.id}: {e}"
                )
                self.stdout.write(
                    self.style.ERROR(
                        f"    FAILED: Article #{article.id} - {e}"
                    )
                )

        # Summary
        self.stdout.write('')
        if dry_run:
            self.stdout.write(
                self.style.SUCCESS(
                    f"Would publish {published_count} article(s), {failed_count} failed"
                )
            )
        else:
            self.stdout.write(
                self.style.SUCCESS(
                    f"Published {published_count} article(s), {failed_count} failed"
                )
            )
