from django.db import models
from django.shortcuts import redirect
from django.template.loader import render_to_string
from modelcluster.contrib.taggit import ClusterTaggableManager
from modelcluster.fields import ParentalKey
from taggit.models import TaggedItemBase
from wagtail.admin.panels import FieldPanel, ObjectList, TabbedInterface
from wagtail.blocks import RichTextBlock
from wagtail.contrib.routable_page.models import route
from wagtail.fields import RichTextField, StreamField
from wagtail.models import Page
from wagtailmetadata.models import MetadataPageMixin

from calendar_utils.models import CalendarMixin
from shared import blocks as shared_blocks
from shared.models import (  # MenuMixin,
    ArticleMixin,
    ExtendedMetadataHomePageMixin,
    ExtendedMetadataPageMixin,
    MainArticlePageMixin,
    MainArticlesPageMixin,
    MainContactPageMixin,
    MainHomePageMixin,
    MainSearchPageMixin,
    MainSimplePageMixin,
    PageInMenuMixin,
    SharedTaggedElectionsArticle,
    SubpageMixin,
)
from shared.utils import make_promote_panels

from . import blocks
from .forms import JekyllImportForm


class ElectionsHomePage(MainHomePageMixin, CalendarMixin):
    # content
    content = StreamField(
        [
            ("carousel", blocks.ElectionsCarouselBlock()),
            ("candidates", blocks.CandidateListBlock()),
            ("secondary_candidates", blocks.CandidateSecondaryListBlock()),
            ("program", shared_blocks.CarouselProgramBlock()),
            (
                "news",
                shared_blocks.NewsBlock(
                    template="styleguide2/includes/organisms/articles/elections/articles_section.html"
                ),
            ),
            ("calendar", blocks.CalendarBlock()),
        ],
        verbose_name="Hlavní obsah",
        blank=True,
        use_json_field=True,
    )
    # settings
    gdpr_and_cookies_page = models.ForeignKey(
        # Keep this a reference to the main website's GDPR page. Not ideal, but works (for now).
        "main.MainSimplePage",
        verbose_name="Stránka pro GDPR",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
    )

    subpage_types = [
        "elections.ElectionsArticlesPage",
        "elections.ElectionsCandidatesPage",
        "elections.ElectionsFaqPage",
        "elections.ElectionsSearchPage",
        "elections.ElectionsFullProgramPage",
        "elections.ElectionsSimplePage",
    ]

    settings_panels = MainHomePageMixin.settings_panels + [FieldPanel("calendar_url")]

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

    ### OTHERS

    class Meta:
        verbose_name = "Volební web"

    @property
    def article_page_model(self):
        return ElectionsArticlePage

    @property
    def articles_page_model(self):
        return ElectionsArticlesPage

    @property
    def search_page_model(self):
        return ElectionsSearchPage

    @property
    def whole_program_page(self):
        return self._first_subpage_of_type(ElectionsFullProgramPage)

    @property
    def root_page(self):
        return self

    def _first_subpage_of_type(self, page_type) -> Page or None:
        try:
            return self.get_descendants().type(page_type).live().specific()[0]
        except IndexError:
            return None

    @route(r"^sdilene/$", name="shared")
    def shared(self, request):
        return self.setup_article_page_context(request)


class ElectionsArticlesPage(MainArticlesPageMixin):
    base_form_class = JekyllImportForm

    parent_page_types = ["elections.ElectionsHomePage"]
    subpage_types = ["elections.ElectionsArticlePage"]


class ElectionsArticleTag(TaggedItemBase):
    content_object = ParentalKey(
        "elections.ElectionsArticlePage",
        on_delete=models.CASCADE,
        related_name="elections_tagged_items",
    )


class ElectionsArticlePage(MainArticlePageMixin):
    author_page = models.ForeignKey(
        "elections.ElectionsCandidatePage",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name="Stránka autora (kandidáta)",
    )
    tags = ClusterTaggableManager(
        through=ElectionsArticleTag,
        related_name="elections_tagged_articles",
        blank=True,
    )
    shared_tags = ClusterTaggableManager(
        verbose_name="Tagy pro sdílení mezi weby",
        through=SharedTaggedElectionsArticle,
        blank=True,
    )

    parent_page_types = ["elections.ElectionsArticlesPage"]
    subpage_types = []


class ElectionsSearchPage(MainSearchPageMixin):
    parent_page_types = ["elections.ElectionsHomePage"]
    subpage_types = []

    @property
    def searchable_models(self) -> list:
        return [
            ElectionsArticlePage,
            ElectionsCandidatePage,
        ]


class ElectionsCandidatesPage(
    ExtendedMetadataPageMixin,
    SubpageMixin,
    MetadataPageMixin,
    PageInMenuMixin,
    Page,
):
    parent_page_types = ["elections.ElectionsHomePage"]
    subpage_types = ["elections.ElectionsCandidatePage"]

    def serve(self, request, *args, **kwargs):
        return redirect(self.root_page.url)

    class Meta:
        verbose_name = "Kandidáti"


class ElectionsCandidatePage(
    ExtendedMetadataPageMixin,
    SubpageMixin,
    MetadataPageMixin,
    PageInMenuMixin,
    Page,
):
    ## FIELDS

    image = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        verbose_name="Obrázek",
        related_name="+",
    )

    position = models.CharField("Pozice/povolání", max_length=64, blank=True, null=True)

    perex = RichTextField()
    description = RichTextField("Popis", blank=True, null=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)

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

    articles_heading = models.CharField(
        "Nadpis sekce s články",
        max_length=32,
        help_text='Např. "Aktuality Mikuláše Peksy".',
    )

    ## PANELS

    content_panels = Page.content_panels + [
        FieldPanel("image"),
        FieldPanel("position"),
        FieldPanel("perex"),
        FieldPanel("description"),
        FieldPanel("email"),
        FieldPanel("phone"),
        FieldPanel("social_links"),
        FieldPanel("articles_heading"),
    ]

    promote_panels = make_promote_panels()

    ## RELATIONS

    parent_page_types = ["elections.ElectionsCandidatesPage"]
    subpage_types = []

    ## META

    class Meta:
        verbose_name = "Kandidát"

    ## FUNCTIONS

    def get_context(self, request) -> dict:
        context = super().get_context(request)

        context["related_candidates_list"] = (
            ElectionsCandidatePage.objects.filter(~models.Q(id=self.id))
            .order_by("?")
            .live()[:3]
        )

        context["article_data_list"] = (
            ElectionsArticlePage.objects.filter(author_page=self.id)
            .order_by("-timestamp")
            .live()[:3]
        )

        return context


class ElectionsFaqPage(
    ExtendedMetadataPageMixin,
    SubpageMixin,
    MetadataPageMixin,
    PageInMenuMixin,
    Page,
):
    ## FIELDS

    # content
    content = StreamField(
        [
            ("person_answers", blocks.PersonFaqAnswersBlock()),
        ],
        verbose_name="Obsah",
        blank=True,
        use_json_field=True,
    )

    all_topics_name = models.CharField(
        "Nadpis štítku pro všechna témata",
        max_length=32,
        help_text="např. 'všechna témata'",
    )

    ## PANELS

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

    promote_panels = make_promote_panels()

    ## RELATIONS

    parent_page_types = ["elections.ElectionsHomePage"]
    subpage_types = []

    class Meta:
        verbose_name = "Otázky a odpovědi"

    ## OTHERS

    def get_topic_names(self) -> list:
        topic_names = [self.all_topics_name]

        for section in self.content:
            topic_names.append(section.value["topic"])

        return topic_names


class ElectionsFullProgramPage(
    ExtendedMetadataPageMixin,
    SubpageMixin,
    MetadataPageMixin,
    PageInMenuMixin,
    Page,
):
    content = StreamField(
        [
            ("richtext", RichTextBlock(label="Text", template="styleguide2/includes/atoms/text/prose_richtext.html")),
            ("popout_block", shared_blocks.ProgramGroupBlockPopout()),
        ],
        verbose_name="Obsah",
        blank=True,
        use_json_field=True,
    )

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

    promote_panels = make_promote_panels()

    ## RELATIONS

    parent_page_types = ["elections.ElectionsHomePage"]
    subpage_types = []

    class Meta:
        verbose_name = "Celá verze programu"

    ## OTHERS
    def get_main_page_program_render(self):
        for block in self.content:
            if block.block_type == "popout_block":
                return render_to_string(
                    "styleguide2/includes/organisms/popouts/popout_list.html",
                    {"categories": block.value["categories"]},
                )

        return ""


class ElectionsSimplePage(MainSimplePageMixin):
    parent_page_types = [
        "elections.ElectionsHomePage",
        "elections.ElectionsSimplePage",
    ]
    subpage_types = ["elections.ElectionsSimplePage"]