from programmer.mixins import MenuContextMixin, BreadcrumbMixin
from django.views.generic import ListView, DetailView
from django.urls import reverse_lazy
from django.contrib import messages
from django.utils.decorators import method_decorator
from django.views.decorators.cache import cache_page
from .models import Article, Category, Comment
from .services import (
    get_published_articles, get_article_by_slug,
    increment_article_views, add_comment_to_article
)
from .forms import CommentForm
from django.http import Http404
from django.shortcuts import get_object_or_404, redirect
from django.contrib.admin.views.decorators import staff_member_required


class ArticleListView(MenuContextMixin, BreadcrumbMixin, ListView):
    """Список статей"""
    model = Article
    template_name = 'blog/article_list.html'
    context_object_name = 'articles'
    paginate_by = 10

    def get_breadcrumbs(self):
        if 'category_slug' in self.kwargs:
            category = get_object_or_404(Category, slug=self.kwargs['category_slug'])
            return [
                {'title': 'Статьи', 'url_name': 'blog:article_list'},
                {'title': category.name, 'url_name': None},
            ]
        return [{'title': 'Статьи', 'url_name': None}]

    def get_queryset(self):
        category_slug = self.kwargs.get('category_slug')
        return get_published_articles(category_slug)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['categories'] = Category.objects.all()
        context.update({
            'title': "Статии | Инструкции",
            'meta_description': (
                "Инструкции по работе в 1С и бизнес-решения"
                "инструкции, статьи помощь 1С."
            ),
            'meta_keywords': (
                "проекты 1С, автоматизация склада 1С, интеграция ТСД 1С, "
                "миграция 1С 7.7, кейсы 1С, примеры работ 1С"
            ),
        })
        if 'category_slug' in self.kwargs:
            context['current_category'] = Category.objects.filter(
                slug=self.kwargs['category_slug']
            ).first()
        return context

    def dispatch(self, *args, **kwargs):
        return super().dispatch(*args, **kwargs)


class ArticleDetailView(MenuContextMixin, BreadcrumbMixin, DetailView):
    """Детальная страница статьи с формой комментария."""
    model = Article
    template_name = 'blog/article_detail.html'
    context_object_name = 'article'

    def get_object(self, queryset=None):
        """Получаем статью по slug, только опубликованные."""
        if not hasattr(self, '_article_cache'):
            article = get_article_by_slug(self.kwargs['slug'])
            if article is None:
                raise Http404("Статья не найдена")
            self._article_cache = article
        return self._article_cache

    def get_breadcrumbs(self):
        article = self.object  # already set by the time breadcrumbs are called
        return [
            {'title': 'Статьи', 'url_name': 'blog:article_list'},
            {
                'title': article.category.name,
                'url_name': 'blog:category_detail',
                'category_slug': article.category.slug,
            },
            {'title': article.title, 'url_name': None},
        ]

    def get(self, request, *args, **kwargs):
        """Устанавливаем self.object один раз, увеличиваем счётчик просмотров."""
        self.object = self.get_object()
        increment_article_views(self.object)
        context = self.get_context_data(object=self.object)
        return self.render_to_response(context)

    def post(self, request, *args, **kwargs):
        """Обработка формы комментария."""
        self.object = self.get_object()
        print("POST data:", request.POST) 

        if not request.user.is_authenticated:
            messages.error(request, "❌ Только авторизованные пользователи могут оставлять комментарии.")
            return redirect(request.path)

        form = CommentForm(request.POST, request=request)
        if form.is_valid():

            parent_id = form.cleaned_data.get('parent_id')
            print(f"parent_id from cleaned_data: {parent_id}") 
            parent = None

            if parent_id:
                try:
                    parent = Comment.objects.get(id=parent_id, article=self.object)
                except Comment.DoesNotExist:
                    pass

            add_comment_to_article(
                article=self.object,
                data=form.cleaned_data,
                user=request.user,
                parent=parent
            )
            messages.success(request, "✅ Ваш комментарий отправлен на модерацию.")
            return redirect(self.object.get_absolute_url())

        # Форма невалидна — показываем страницу снова с ошибками
        context = self.get_context_data(object=self.object, form=form)
        return self.render_to_response(context)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)

        # Используем form из kwargs если передана (например при ошибке валидации)
        if 'form' not in kwargs:
            context['form'] = CommentForm(request=self.request)
        
        root_comments = self.object.comments.filter(parent__isnull=True, is_moderated=True)
        context['root_comments'] = root_comments

        context.update({
            'moderated_comments': self.object.comments.filter(is_moderated=True),
            'user_is_authenticated': self.request.user.is_authenticated,
            'title': self.object.get_seo_title(),
            'meta_description': self.object.get_seo_description(),
            'meta_keywords': ', '.join(
                tag.name for tag in self.object.tags.all()
            ),
        })
        return context

@method_decorator(staff_member_required, name='dispatch')
class ArticleDraftPreviewView(MenuContextMixin, BreadcrumbMixin, DetailView):
    model = Article
    template_name = 'blog/article_detail.html'  # используем тот же шаблон
    context_object_name = 'article'

    def get_queryset(self):
        # Для предпросмотра показываем даже неопубликованные статьи
        return Article.objects.all()  # без фильтрации по is_published