from captcha.fields import CaptchaField
from django.db import models
from django.shortcuts import redirect
from django.utils.translation import gettext_lazy
from modelcluster.contrib.taggit import ClusterTaggableManager
from modelcluster.fields import ParentalKey, ParentalManyToManyField
from taggit.models import TaggedItemBase
from wagtail import blocks
from wagtail.admin.panels import (
    FieldPanel,
    InlinePanel,
    MultiFieldPanel,
    ObjectList,
    PageChooserPanel,
    TabbedInterface,
)
from wagtail.contrib.forms.models import AbstractForm, AbstractFormField
from wagtail.contrib.forms.panels import FormSubmissionsPanel
from wagtail.fields import RichTextField, StreamField
from wagtail.models import Page
from wagtailmetadata.models import MetadataPageMixin

from calendar_utils.models import CalendarMixin
from shared.blocks import (
    DEFAULT_CONTENT_BLOCKS,
    CalendarBlock,
    NavbarMenuItemBlock,
    NewsBlock,
    NewsletterSubscriptionBlock,
)
from shared.const import RICH_TEXT_DEFAULT_FEATURES
from shared.models import (
    CalendarMixin,
    CustomLogoMixin,
    EcomailNewsletterMixin,
    ExtendedMetadataPageMixin,
    FbEventsMixin,
    MainArticlePageMixin,
    MainArticlesPageMixin,
    MainHomePageMixin,
    MainMenuMixin,
    MainPeoplePageMixin,
    MainPersonPageMixin,
    MainSearchPageMixin,
    PageInMenuMixin,
    PdfPageMixin,
    ScrollProgressMixin,
    SharedTaggedUniwebArticle,
    SocialMixin,
    SubpageMixin,
)
from shared.utils import subscribe_to_ecomail_newsletter
from shared_legacy.models import FooterMixin as LegacyFooterMixin
from shared_legacy.utils import make_promote_panels

from .blocks import PeopleGroupBlock, TeamBlock, UniwebSubpageFormBlock
from .forms import UniwebArticlesPageForm, UniwebHomePageAdminForm

CONTENT_STREAM_BLOCKS = DEFAULT_CONTENT_BLOCKS + [
    ("calendar", CalendarBlock()),
    ("subpage_form", UniwebSubpageFormBlock()),
]


class UniwebArticleTag(TaggedItemBase):
    content_object = ParentalKey(
        "uniweb.UniwebArticlePage",
        on_delete=models.CASCADE,
        related_name="tagged_items",
    )


class UniwebHomePage(
    CalendarMixin,
    LegacyFooterMixin,
    PageInMenuMixin,
    ScrollProgressMixin,
    CustomLogoMixin,
    EcomailNewsletterMixin,
    FbEventsMixin,
    MainHomePageMixin,
):
    base_form_class = UniwebHomePageAdminForm

    ### FIELDS

    show_transparent_header = models.BooleanField(
        default=False,
        verbose_name="Průhledná hlavička?",
        help_text=(
            "Pokud je toto pole zaškrtlé, obrázek na pozadí hlavičky " "se neztmaví."
        ),
    )

    main_image = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        verbose_name="Obrázek na pozadí hlavičky",
        related_name="+",
    )

    menu_button_name = models.CharField(
        verbose_name="Text na tlačítku pro zapojení", max_length=16
    )

    menu_button_content = StreamField(
        [
            ("navbar_menu_item", NavbarMenuItemBlock()),
        ],
        verbose_name="Obsah tlačítka pro zapojení",
        blank=True,
        use_json_field=True,
    )

    calendar_page = models.ForeignKey(
        "UniwebCalendarPage",
        verbose_name="Stránka s kalendářem",
        on_delete=models.PROTECT,
        null=True,
        blank=True,
    )

    content = StreamField(
        CONTENT_STREAM_BLOCKS
        + [
            ("newsletter", NewsletterSubscriptionBlock()),
            (
                "news_block",
                NewsBlock(
                    template="styleguide2/includes/organisms/articles/district/articles_section.html",
                    group="3. Ostatní",
                ),
            ),
        ],
        verbose_name="obsah stránky",
        blank=True,
        use_json_field=True,
    )

    hide_footer = models.BooleanField(
        "skrýt patičku", default=False, help_text="Chcete skrýt patičku?"
    )
    show_logo = models.BooleanField(
        "zobrazit logo", default=True, help_text="Chcete v hlavičce ukazovat logo?"
    )
    calendar_button_text = models.CharField(
        "Text tlačítka kalendáře", max_length=256, default="Kalendář"
    )

    footer_extra_content = RichTextField(
        verbose_name="Extra obsah pod šedou patičkou",
        blank=True,
        features=RICH_TEXT_DEFAULT_FEATURES,
    )

    content_is_full_width = models.BooleanField(
        "Roztáhnout obsah na celou šířku stránky", default=False
    )
    content_is_centered = models.BooleanField("Vycentrovat obsah", default=False)

    newsletter_list_id = models.CharField(
        "ID Mailtrain newsletteru",
        max_length=20,
        blank=True,
        null=True,
        help_text="ID newsletteru z Mailtrainu. Po vyplnění se formulář pro odběr newsletteru zobrazí na úvodní stránce a na stránce s kontakty.",
    )

    ### PANELS

    content_panels = MainHomePageMixin.content_panels + [
        FieldPanel("main_image"),
        FieldPanel("show_transparent_header"),
    ]

    settings_panels = [
        MultiFieldPanel(
            [
                FieldPanel("matomo_id"),
                FieldPanel("title_suffix"),
                FieldPanel("meta_title_suffix"),
            ],
            "Obecné nastavení webu",
        ),
        MultiFieldPanel(
            [
                FieldPanel("calendar_url"),
                PageChooserPanel("calendar_page"),
            ],
            "Kalendář",
        ),
        MultiFieldPanel(
            [
                FieldPanel("content_is_full_width"),
                FieldPanel("content_is_centered"),
            ],
            "Zarovnání obsahu",
        ),
        MultiFieldPanel(
            [
                FieldPanel("ecomail_newsletter_list_id"),
                FieldPanel("ecomail_newsletter_list_tags"),
                FieldPanel("ecomail_newsletter_list_source"),
                FieldPanel("newsletter_list_id"),
            ],
            "Newsletter",
        ),
        FieldPanel("fallback_image"),
        FieldPanel("fbevents_id"),
    ] + ScrollProgressMixin.settings_panels

    menu_panels = (
        [
            MultiFieldPanel(
                [
                    FieldPanel("dark_logo"),
                    FieldPanel("light_logo"),
                    FieldPanel("show_logo"),
                ],
                "Logo",
            )
        ]
        + MainMenuMixin.menu_panels
        + SocialMixin.menu_panels
        + [
            FieldPanel("menu_button_name"),
            FieldPanel("menu_button_content"),
            FieldPanel("calendar_button_text"),
        ]
    )

    footer_panels = [
        FieldPanel("hide_footer"),
        FieldPanel("footer_extra_content"),
    ] + MainHomePageMixin.footer_panels

    edit_handler = TabbedInterface(
        [
            ObjectList(content_panels, heading="Obsah"),
            ObjectList(menu_panels, heading="Hlavička"),
            ObjectList(footer_panels, heading="Patička"),
            ObjectList(settings_panels, heading="Nastavení"),
            ObjectList(MainHomePageMixin.promote_panels, heading="Metadata"),
        ]
    )

    ### RELATIONS

    subpage_types = [
        "uniweb.UniwebFlexiblePage",
        "uniweb.UniwebArticlesIndexPage",
        "uniweb.UniwebFormPage",
        "uniweb.UniwebPeoplePage",
        "uniweb.UniwebCalendarPage",
        "uniweb.UniwebSearchPage",
    ]

    ### OTHERS

    class Meta:
        verbose_name = "Univerzální web"

    @property
    def gdpr_and_cookies_page(self):
        from main.models import MainHomePage

        return MainHomePage.objects.first().gdpr_and_cookies_page

    @property
    def article_page_model(self):
        return UniwebArticlePage

    @property
    def articles_page_model(self):
        return UniwebArticlesIndexPage

    @property
    def people_page_model(self):
        return UniwebPeoplePage

    @property
    def search_page_model(self):
        return UniwebSearchPage

    @property
    def root_page(self):
        return self

    @property
    def has_calendar(self):
        return self.calendar_id is not None


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

    show_transparent_header = models.BooleanField(
        default=False,
        verbose_name="Průhledná hlavička?",
        help_text=(
            "Pokud je toto pole zaškrtlé, obrázek na pozadí hlavičky " "se neztmaví."
        ),
    )

    main_image = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        verbose_name="Obrázek na pozadí hlavičky",
        related_name="+",
    )

    content = StreamField(
        CONTENT_STREAM_BLOCKS + [("newsletter", NewsletterSubscriptionBlock())],
        verbose_name="obsah stránky",
        blank=True,
        use_json_field=True,
    )

    ### PANELS

    promote_panels = make_promote_panels()

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

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

    ### RELATIONS

    parent_page_types = [
        "uniweb.UniwebHomePage",
        "uniweb.UniwebFlexiblePage",
        "uniweb.UniwebFormPage",
    ]
    subpage_types = [
        "uniweb.UniwebFlexiblePage",
        "uniweb.UniwebFormPage",
    ]

    ### OTHERS

    class Meta:
        verbose_name = "Flexibilní stránka"


class UniwebCalendarPage(
    PageInMenuMixin, SubpageMixin, MetadataPageMixin, CalendarMixin, Page
):
    """
    Page for displaying full calendar
    """

    ### PANELS

    content_panels = Page.content_panels + [FieldPanel("calendar_url")]

    ### RELATIONS

    parent_page_types = [
        "uniweb.UniwebHomePage",
    ]
    subpage_types = []

    ### OTHERS

    class Meta:
        verbose_name = "Stránka s kalendářem"


class UniwebArticlesIndexPage(MainArticlesPageMixin):
    base_form_class = UniwebArticlesPageForm

    displayed_tags = ParentalManyToManyField(
        "uniweb.UniwebArticleTag",
        verbose_name="Z tohoto webu",
        related_name="+",
        blank=True,
    )

    displayed_shared_tags = ParentalManyToManyField(
        "shared.SharedTag",
        verbose_name="Sdílecí",
        related_name="+",
        blank=True,
    )

    ### RELATIONS

    parent_page_types = ["uniweb.UniwebHomePage"]
    subpage_types = ["uniweb.UniwebArticlePage"]

    ### PANELS

    edit_handler = TabbedInterface(
        [
            ObjectList(MainArticlesPageMixin.content_panels, heading="Obsah"),
            ObjectList(MainArticlesPageMixin.promote_panels, heading="Metadata"),
        ]
    )


class UniwebArticlePage(MainArticlePageMixin):
    author_page = models.ForeignKey(
        "uniweb.UniwebPersonPage", on_delete=models.SET_NULL, null=True, blank=True
    )
    tags = ClusterTaggableManager(through=UniwebArticleTag, blank=True)
    shared_tags = ClusterTaggableManager(
        verbose_name="Štítky pro sdílení mezi weby",
        through=SharedTaggedUniwebArticle,
        blank=True,
    )

    ### RELATIONS

    parent_page_types = ["uniweb.UniwebArticlesIndexPage"]
    subpage_types = ["uniweb.UniwebPdfPage"]


class UniwebFormField(AbstractFormField):
    page = ParentalKey(
        "UniwebFormPage", on_delete=models.CASCADE, related_name="form_fields"
    )


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

    show_transparent_header = models.BooleanField(
        default=False,
        verbose_name="Průhledná hlavička?",
        help_text=(
            "Pokud je toto pole zaškrtlé, obrázek na pozadí hlavičky " "se neztmaví."
        ),
    )

    main_image = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        verbose_name="Obrázek na pozadí hlavičky",
        related_name="+",
    )

    content_before = StreamField(
        CONTENT_STREAM_BLOCKS,
        verbose_name="obsah stránky před formulářem",
        blank=True,
        use_json_field=True,
    )
    content_after = StreamField(
        CONTENT_STREAM_BLOCKS,
        verbose_name="obsah stránky za formulářem",
        blank=True,
        use_json_field=True,
    )
    content_landing = StreamField(
        CONTENT_STREAM_BLOCKS,
        verbose_name="Obsah stránky zobrazené po odeslání formuláře",
        blank=True,
        use_json_field=True,
    )

    show_in_parent_page = models.BooleanField(
        verbose_name="Ukazovat obsah formuláře v nadřazené stránce?",
        default=False,
        help_text=(
            "Pokud je toto pole zaškrtnuté, formulář se přesune do nadřazené stránky "
            "a stránka jemu nadřazená bude nedostupná."
        ),
    )

    subscribe_to_ecomail = models.BooleanField(
        verbose_name="Automaticky odebírat vyplněné údaje do Ecomail NL?",
        default=False,
    )

    name_and_surname_field_id = models.CharField(
        verbose_name="ID jméno & příjmení fieldu", blank=True, null=True
    )

    email_field_id = models.CharField(
        verbose_name="ID email fieldu", blank=True, null=True
    )

    submission_button_text = models.CharField(
        verbose_name="Text tlačítka pro odeslání formuláře",
        default="Odeslat",
    )

    ### PANELS

    content_panels = AbstractForm.content_panels + [
        FieldPanel("main_image"),
        FieldPanel("show_transparent_header"),
        FieldPanel("content_before"),
        InlinePanel("form_fields", label="formulář"),
        FieldPanel("submission_button_text"),
        FieldPanel("content_after"),
        FieldPanel("content_landing"),
    ]

    promote_panels = make_promote_panels()

    submissions_panels = [FormSubmissionsPanel()]

    advanced_panels = [
        FieldPanel("show_in_parent_page"),
        FieldPanel("subscribe_to_ecomail"),
        FieldPanel("name_and_surname_field_id"),
        FieldPanel("email_field_id"),
    ]

    edit_handler = TabbedInterface(
        [
            ObjectList(content_panels, heading=gettext_lazy("Content")),
            ObjectList(promote_panels, heading=gettext_lazy("Promote")),
            ObjectList(advanced_panels, heading="Pokročilé"),
            ObjectList(submissions_panels, heading="Data z formuláře"),
        ]
    )

    ### RELATIONS

    parent_page_types = [
        "uniweb.UniwebHomePage",
        "uniweb.UniwebFlexiblePage",
        "uniweb.UniwebFormPage",
    ]
    subpage_types = ["uniweb.UniwebFlexiblePage", "uniweb.UniwebFormPage"]

    ### OTHERS

    def serve(self, request):
        if request.method == "GET" and self.show_in_parent_page:
            if hasattr(self, "root_page"):
                return redirect(self.root_page.url)
            else:
                return redirect("/")

        return super().serve(request)

    def process_form_submission(self, form):
        cleaned_data = form.cleaned_data

        if (
            hasattr(self, "root_page")
            and self.root_page
            and self.subscribe_to_ecomail
            and self.name_and_surname_field_id in cleaned_data
            and self.email_field_id in cleaned_data
        ):
            name_and_surname = cleaned_data[self.name_and_surname_field_id]
            name_and_surname = name_and_surname.split(" ")

            name = ""
            surname = ""

            if len(name_and_surname) > 1:
                name = name_and_surname[0]
                surname = " ".join(name_and_surname[1:])
            else:
                name = name_and_surname[0]

            custom_data = {
                "name": name,
            }

            if surname != "":
                custom_data["surname"] = surname

            subscribe_to_ecomail_newsletter(
                cleaned_data[self.email_field_id],
                self.root_page.ecomail_newsletter_list_tags,
                self.root_page.ecomail_newsletter_list_source,
                self.root_page.ecomail_newsletter_list_id,
                custom_data,
            )

        super().process_form_submission(form)

    class Meta:
        verbose_name = "Formulářová stránka"

    def get_form_class(self):
        form = super().get_form_class()
        form.base_fields["captcha"] = CaptchaField(label="opište písmena z obrázku")
        return form


class UniwebPersonPage(MainPersonPageMixin):
    ### FIELDS

    job = models.CharField(
        "Povolání",
        max_length=128,
        blank=True,
        null=True,
        help_text="Např. 'Informatik'",
    )

    city = models.CharField("Město/obec", max_length=64, blank=True, null=True)
    age = models.IntegerField("Věk", blank=True, null=True)

    is_pirate = models.BooleanField("Je členem Pirátské strany?", default=True)
    other_party = models.CharField(
        "Strana",
        max_length=64,
        blank=True,
        null=True,
        help_text="Vyplňte pokud osoba není Pirát",
    )
    other_party_logo = models.ForeignKey(
        "wagtailimages.Image",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        related_name="+",
        verbose_name="Logo strany",
        help_text="Vyplňte pokud osoba není Pirát",
    )

    ### PANELS

    content_panels = Page.content_panels + [
        MultiFieldPanel(
            [
                FieldPanel("main_image"),
                FieldPanel("profile_image"),
            ],
            heading="Obrázky",
        ),
        MultiFieldPanel(
            [FieldPanel("before_name"), FieldPanel("after_name")],
            heading="Titul",
        ),
        MultiFieldPanel(
            [
                FieldPanel("is_pirate"),
                FieldPanel("other_party"),
                FieldPanel("other_party_logo"),
            ],
            heading="Politická příslušnost",
        ),
        MultiFieldPanel(
            [
                FieldPanel("position"),
                FieldPanel("job"),
                FieldPanel("city"),
                FieldPanel("age"),
            ],
            heading="Základní informace",
        ),
        MultiFieldPanel([FieldPanel("perex"), FieldPanel("text")], heading="Popis"),
        MultiFieldPanel(
            [
                FieldPanel("email"),
                FieldPanel("phone"),
                FieldPanel("social_links"),
            ],
            heading="Kontakt",
        ),
        FieldPanel("calendar_url"),
        FieldPanel("related_people"),
    ]

    ### RELATIONS

    parent_page_types = ["uniweb.UniwebPeoplePage"]
    subpage_types = []


class UniwebPeoplePage(MainPeoplePageMixin):
    ### FIELDS

    content = StreamField(
        [
            (
                "text",
                blocks.RichTextBlock(
                    label="Textový editor",
                    features=RICH_TEXT_DEFAULT_FEATURES,
                    template="styleguide2/includes/atoms/text/prose_richtext.html",
                ),
            ),
            ("people_group", PeopleGroupBlock()),
            ("team_group", TeamBlock()),
        ],
        verbose_name="Obsah stránky",
        blank=True,
        use_json_field=True,
    )

    ### RELATIONS

    parent_page_types = ["uniweb.UniwebHomePage"]
    subpage_types = ["uniweb.UniwebPersonPage"]


class UniwebPdfPage(
    PageInMenuMixin, MetadataPageMixin, SubpageMixin, PdfPageMixin, Page
):
    """
    Single pdf page display
    """

    ### RELATIONS
    parent_page_types = [
        "uniweb.UniwebHomePage",
        "uniweb.UniwebArticlePage",
    ]
    subpage_types = []

    ### PANELS

    content_panels = Page.content_panels + PdfPageMixin.content_panels

    ### OTHER

    class Meta:
        verbose_name = "PDF stránka"


class UniwebSearchPage(MainSearchPageMixin):
    ### RELATIONS

    parent_page_types = ["uniweb.UniwebHomePage"]

    ### OTHER

    @property
    def searchable_models(self):
        return [
            UniwebArticlePage,
            UniwebPersonPage,
            UniwebFlexiblePage,
        ]