from datetime import timedelta
from functools import cached_property

from django.conf import settings
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,
    HelpPanel,
    MultiFieldPanel,
    ObjectList,
    TabbedInterface,
)
from wagtail.contrib.routable_page.models import 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 .forms import JekyllImportForm
from .menu import MenuMixin


class ARTICLE_TYPES(models.IntegerChoices):
    WORK_TIMELINE = 1, "Článek na timeline Piráti pracují"
    PRESS_RELEASE = 2, "Tisková zpráva"


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.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 MainArticlesPage(
    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,
    )
    last_import_log = models.TextField(
        "Výstup z posledního importu", null=True, blank=True
    )

    import_panels = [
        MultiFieldPanel(
            [
                FieldPanel("do_import"),
                FieldPanel("collection"),
                FieldPanel("dry_run"),
                FieldPanel("jekyll_repo_url"),
                FieldPanel("readonly_log"),
                HelpPanel(
                    "Import provádějte vždy až po vytvoření stránky aktualit. "
                    'Pro uložení logu je nutné volit možnost "Publikovat", nikoliv'
                    'pouze "Uložit koncept". '
                    "Import proběhne na pozadí a může trvat až několik minut. "
                    "Dejte si po spuštění importu kávu a potom obnovte stránku pro "
                    "zobrazení výsledku importu."
                ),
            ],
            "import z Jekyll repozitáře",
        ),
    ]

    ### RELATIONS

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

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

    ### EDIT HANDLERS

    edit_handler = TabbedInterface(
        [
            ObjectList(content_panels, heading="Obsah"),
            ObjectList(promote_panels, heading="Propagovat"),
            ObjectList(import_panels, heading="Import"),
        ]
    )

    ### OTHERS

    base_form_class = JekyllImportForm

    class Meta:
        verbose_name = "Rozcestník článků"

    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
    article_type = models.PositiveSmallIntegerField(
        "Typ článku", choices=ARTICLE_TYPES.choices, default=ARTICLE_TYPES.PRESS_RELEASE
    )

    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("article_type"),
        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 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
    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,
    )

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

    facebook = models.URLField("Odkaz na Facebook", blank=True, null=True)
    twitter = models.URLField("Odkaz na Twitter", blank=True, null=True)
    instagram = models.URLField("Odkaz na Instagram", blank=True, null=True)

    settings_panels = []

    ### RELATIONS

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

    ### PANELS
    content_panels = Page.content_panels + [
        FieldPanel("before_name"),
        FieldPanel("after_name"),
        FieldPanel("position"),
        FieldPanel("perex"),
        FieldPanel("twitter_username"),
        FieldPanel("text"),
        FieldPanel("email"),
        FieldPanel("phone"),
        FieldPanel("facebook"),
        FieldPanel("twitter"),
        FieldPanel("instagram"),
    ]

    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"