from datetime import timedelta
from functools import cached_property

from django.conf import settings
from django.core.paginator import Paginator
from django.db import models
from django.http import HttpResponseRedirect
from django.shortcuts import render
from django.utils import timezone
from modelcluster.contrib.taggit import ClusterTaggableManager
from modelcluster.fields import ParentalKey
from taggit.models import TaggedItemBase
from wagtail.admin.edit_handlers import FieldPanel, ObjectList, TabbedInterface
from wagtail.contrib.routable_page.models import RoutablePageMixin, route
from wagtail.core.blocks import CharBlock, PageChooserBlock, RichTextBlock
from wagtail.core.fields import RichTextField, StreamField
from wagtail.core.models import Page
from wagtailmetadata.models import MetadataPageMixin

from elections2021.constants import REGION_CHOICES  # pozor, import ze sousedního modulu
from shared.const import RICH_TEXT_DEFAULT_FEATURES
from shared.forms import SubscribeForm
from shared.models import (  # MenuMixin,
    ArticleMixin,
    ExtendedMetadataHomePageMixin,
    ExtendedMetadataPageMixin,
    SubpageMixin,
)
from shared.utils import make_promote_panels, subscribe_to_newsletter
from tuning import admin_help
from twitter_utils.models import Tweet

from . import blocks
from .menu import MenuMixin


class MainHomePage(MenuMixin, ExtendedMetadataHomePageMixin, MetadataPageMixin, Page):

    # header

    contact_newcomers = models.URLField(
        "URL pro zájemce o členství",
        blank=True,
        null=True,
        default="https://nalodeni.pirati.cz",
    )

    donation_page = models.URLField(
        "URL pro příjem darů (tlačítko Dary)",
        blank=True,
        null=True,
        default="https://dary.pirati.cz",
    )

    # content
    content = StreamField(
        [
            ("carousel", blocks.HomePageCarouselBlock()),
            ("news", blocks.NewsBlock()),
            ("people", blocks.PeopleOverviewBlock()),
            ("regions", blocks.RegionsBlock()),
            ("tweets", blocks.TweetsBlock()),
            ("boxes", blocks.BoxesBlock()),
        ],
        verbose_name="Hlavní obsah",
        blank=True,
    )

    # footer
    footer_other_links = StreamField(
        [
            ("other_links", blocks.OtherLinksBlock()),
        ],
        verbose_name="Bloky dalších odkazů v zápatí webu",
        blank=True,
    )

    footer_person_list = StreamField(
        [("person", blocks.PersonContactBlock())],
        verbose_name="Osoby v zápatí webu",
        blank=True,
        max_num=6,
    )

    # settings
    matomo_id = models.IntegerField(
        "Matomo ID pro sledování návštěvnosti", blank=True, null=True
    )

    social_links = StreamField(
        [
            ("social_links", blocks.SocialLinkBlock()),
        ],
        verbose_name="Odkazy na sociální sítě v zápatí webu",
        blank=True,
    )

    twitter_usernames = StreamField(
        [("username", CharBlock(label="Twitter uživatelské jméno"))],
        verbose_name="Uživatelská jména pro synchronizované twitter účty",
        blank=True,
        max_num=6,
    )

    content_panels = Page.content_panels + [
        FieldPanel("content"),
        FieldPanel("footer_other_links"),
        FieldPanel("footer_person_list"),
    ]

    settings_panels = [
        FieldPanel("contact_newcomers"),
        FieldPanel("donation_page"),
        FieldPanel("social_links"),
        FieldPanel("matomo_id"),
        FieldPanel("twitter_usernames"),
    ]

    ### EDIT HANDLERS

    edit_handler = TabbedInterface(
        [
            ObjectList(content_panels, heading="Obsah"),
            ObjectList(settings_panels, heading="Nastavení"),
            ObjectList(MenuMixin.menu_panels, heading="Menu"),
        ]
    )

    ### RELATIONS

    subpage_types = [
        "main.MainWorkPage",
        "main.MainArticlesPage",
        "main.MainProgramPage",
        "main.MainPeoplePage",
        "main.MainPersonPage",
        "main.MainContactPage",
    ]

    ### OTHERS

    class Meta:
        verbose_name = "HomePage pirati.cz"

    @staticmethod
    def get_404_response(request):
        return render(request, "main/404.html", status=404)

    def get_context(self, request, *args, **kwargs):
        context = super().get_context(request, args, kwargs)
        context["tweet_list"] = Tweet.objects.order_by("-twitter_id")[:4]
        return context

    @cached_property
    def newsletter_subscribe_url(self):
        return self.url + self.reverse_subpage("newsletter_subscribe")

    @property
    def root_page(self):
        return self

    @route(r"^prihlaseni-k-newsletteru/$")
    def newsletter_subscribe(self, request):
        if request.method == "POST":
            form = SubscribeForm(request.POST)
            if form.is_valid():
                subscribe_to_newsletter(
                    form.cleaned_data["email"],
                    settings.PIRATICZ_NEWSLETTER_ID,
                    settings.PIRATICZ_NEWSLETTER_SOURCE,
                )
                try:
                    page = (
                        Page.objects.filter(id=form.cleaned_data["return_page_id"])
                        .live()
                        .first()
                    )
                    return HttpResponseRedirect(page.full_url)
                except Page.DoesNotExist:
                    return HttpResponseRedirect(self.url)
        return HttpResponseRedirect(self.url)


class MainWorkPage(ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, Page):
    perex = models.TextField()
    timeline = StreamField(  # TODO delete
        [
            (
                "article_list",
                PageChooserBlock(
                    page_type="main.MainArticlePage", label="Vybrat aktualitu"
                ),
            )
        ],
        verbose_name="Timeline",
        blank=True,
    )

    ### RELATIONS

    parent_page_types = ["main.MainHomePage"]
    subpage_types = []

    ### PANELS
    content_panels = Page.content_panels + [FieldPanel("perex"), FieldPanel("timeline")]

    ### OTHERS

    class Meta:
        verbose_name = "Piráti pracují"

    def get_article_data_list(self):
        last_month = timezone.now().today().replace(day=1) - timedelta(days=1)
        first_day_of_last_month = last_month.replace(day=1)

        sorted_article_qs = MainArticlePage.objects.filter(
            date__gt=first_day_of_last_month
        ).order_by("-date")

        article_data_list = []

        current_month_data = self.get_empty_month_data(timezone.now().date())

        article_counter = 1
        for article in sorted_article_qs:
            if article.date.month != current_month_data["month_number"]:
                article_data_list.append(current_month_data)  # append completed month
                current_month_data = self.get_empty_month_data(article.date)
                article_counter = 1

            current_column = "left_column" if article_counter % 2 else "right_column"
            current_month_data[current_column].append(article)
            article_counter += 1

        article_data_list.append(current_month_data)  # last iteration

        return article_data_list

    def get_context(self, request, *args, **kwargs):
        ctx = super().get_context(request, args, kwargs)
        ctx["article_data_list"] = self.get_article_data_list()
        return ctx

    @staticmethod
    def get_empty_month_data(date_obj):
        return {
            "month_number": date_obj.month,
            "month_text": date_obj.strftime("%B"),
            "left_column": [],
            "right_column": [],
        }


class MainArticleTag(TaggedItemBase):
    content_object = ParentalKey("main.MainArticlePage", on_delete=models.CASCADE)


class MainArticlePage(
    ArticleMixin, ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, Page
):

    ### FIELDS

    content = StreamField(
        [
            ('text', RichTextBlock(template="")),
            ('quote', blocks.ArticleQuoteBlock()),
            ('download', blocks.ArticleDownloadBlock()),
            ('image', blocks.ArticleImageBlock())
        ],
        verbose_name="Článek",
        blank=True,
    )

    author_page = models.ForeignKey(
        "main.MainPersonPage",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name="Stránka autora (osoby)",
    )
    region = models.IntegerField(
        choices=REGION_CHOICES,
        null=True,
        blank=True,
        verbose_name="Kraj",
        help_text="Kraj, ke kterému se článek vztahuje",
    )
    tags = ClusterTaggableManager(through=MainArticleTag, blank=True)

    ### PANELS

    content_panels = ArticleMixin.content_panels + [
        FieldPanel("author_page"),
        FieldPanel("region"),
        FieldPanel("tags"),
    ]

    promote_panels = make_promote_panels(
        admin_help.build(admin_help.NO_SEO_TITLE, admin_help.NO_DESCRIPTION_USE_PEREX),
        search_image=False,
    )

    ### RELATIONS

    parent_page_types = ["main.MainArticlesPage"]
    subpage_types = []

    ### OTHERS

    class Meta:
        verbose_name = "Aktualita"

    # def get_context(self, request): chceme/nechceme?
    #     context = super().get_context(request)
    #     context["related_articles"] = (
    #         self.get_siblings(inclusive=False)
    #         .live()
    #         .specific()
    #         .order_by("-mainarticlepage__date")[:3]
    #     )
    #     return context


class MainArticlesPage(
    RoutablePageMixin, ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, Page
):
    def get_context(self, request):
        context = super().get_context(request)
        context["articles"] = Paginator(
            self.get_children().live().specific().order_by("-mainarticlepage__date"),
            12,  # nevím, návrh nemáme
        ).get_page(request.GET.get("page"))
        return context

    @route(r"^tagy/$", name="tags")
    def tags(self, request):
        return render(
            request,
            "main/main_tags_page.html",
            context=self.get_tags_page_context(request=request),
        )

    ### RELATIONS

    parent_page_types = ["main.MainHomePage"]
    subpage_types = ["main.MainArticlePage"]

    ### OTHERS

    class Meta:
        verbose_name = "Aktuality"


class MainProgramPage(ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, Page):

    ### FIELDS

    perex = models.TextField()
    program = StreamField(
        [("program_group", blocks.ProgramGroupBlock(label="Část programu"))],
        verbose_name="Program",
        blank=True,
    )

    ### PANELS

    content_panels = Page.content_panels + [FieldPanel("perex"), FieldPanel("program")]

    promote_panels = make_promote_panels()

    settings_panels = []

    ### RELATIONS

    parent_page_types = ["main.MainHomePage"]
    subpage_types = []

    ### OTHERS

    class Meta:
        verbose_name = "Program"


class MainPeoplePage(ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, Page):

    ### FIELDS

    perex = models.TextField()
    people = StreamField(
        [("people_group", blocks.PeopleGroupBlock(label="Seznam osob"))],
        verbose_name="Lidé",
        blank=True,
    )

    ### PANELS

    content_panels = Page.content_panels + [FieldPanel("perex"), FieldPanel("people")]

    promote_panels = make_promote_panels()

    settings_panels = []

    ### RELATIONS

    parent_page_types = ["main.MainHomePage"]
    subpage_types = ["main.MainPersonPage"]

    ### OTHERS

    class Meta:
        verbose_name = "Lidé"


class MainPersonPage(ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, Page):

    ### FIELDS
    main_image = models.ImageField("Hlavní obrázek", blank=True, null=True)
    profile_image = models.ImageField("Profilový obrázek", blank=True, null=True)
    before_name = models.CharField(
        "Tituly před jménem", max_length=16, blank=True, null=True
    )
    after_name = models.CharField(
        "Tituly za jménem", max_length=16, blank=True, null=True
    )
    position = models.CharField(
        "Pozice/povolání", max_length=128, blank=True, null=True
    )
    perex = models.TextField()
    text = RichTextField()

    twitter_username = models.CharField(
        "Uživatelské jméno twitter pro získání příspěvků",
        blank=True,
        null=True,
        max_length=32,
    )

    social_links = StreamField(
        [
            ("social_links", blocks.SocialLinkBlock()),
        ],
        verbose_name="Odkazy na sociální sítě",
        blank=True,
    )

    people = StreamField(
        [("people_group", blocks.PeopleGroupBlock(label="Seznam osob"))],
        verbose_name="Lidé",
        blank=True,
    )

    email = models.CharField("E-mail", max_length=128, blank=True, null=True)
    phone = models.CharField("Telefonní kontakt", max_length=16, blank=True, null=True)

    settings_panels = []

    ### RELATIONS

    parent_page_types = ["main.MainPeoplePage"]
    subpage_types = []

    ### PANELS
    content_panels = Page.content_panels + [
        FieldPanel("main_image"),
        FieldPanel("profile_image"),
        FieldPanel("before_name"),
        FieldPanel("after_name"),
        FieldPanel("position"),
        FieldPanel("perex"),
        FieldPanel("twitter_username"),
        FieldPanel("text"),
        FieldPanel("email"),
        FieldPanel("phone"),
        FieldPanel("social_links"),
        FieldPanel("people"),
    ]

    def get_context(self, request):
        context = super().get_context(request)
        context["article_page_list"] = MainArticlePage.objects.filter(
            author_page=self.id
        )
        context["tweet_list"] = Tweet.objects.filter(
            author_username=self.twitter_username
        )
        return context

    ### OTHERS

    class Meta:
        verbose_name = "Detail osoby"
        # ordering = ("title",)

    def get_background_photo(self):
        """
        Vrací background_photo pro pozadí na stránce, pokud není nastaveno,
        vezme falbback z homepage
        """
        return (
            self.background_photo
            if self.background_photo
            else self.root_page.fallback_image
        )


class MainContactPage(ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, Page):

    ### FIELDS

    contact_people = StreamField(
        [("item", blocks.PersonContactBlock())],
        verbose_name="Kontaktní osoby",
        blank=True,
    )
    contact_boxes = StreamField(
        [("item", blocks.PersonContactBlock())],
        verbose_name="Kontaktní boxy",
        blank=True,
    )
    text = RichTextField("Text", blank=True, features=RICH_TEXT_DEFAULT_FEATURES)

    ### PANELS

    content_panels = Page.content_panels + [
        FieldPanel("contact_people"),
        FieldPanel("contact_boxes"),
        FieldPanel("text"),
    ]

    promote_panels = make_promote_panels()

    settings_panels = []

    ### RELATIONS

    parent_page_types = ["main.MainHomePage"]
    subpage_types = []

    ### OTHERS

    class Meta:
        verbose_name = "Kontakty"