from datetime import date, datetime

from django.contrib import messages
from django.core.mail import EmailMessage
from django.db import models
from django.shortcuts import render
from modelcluster.contrib.taggit import ClusterTaggableManager
from modelcluster.fields import ParentalKey, ParentalManyToManyField
from taggit.models import TaggedItemBase
from wagtail.admin.panels import FieldPanel, HelpPanel, MultiFieldPanel
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 shared import blocks as shared_blocks
from shared.const import RICH_TEXT_DEFAULT_FEATURES
from shared.models import (  # MenuMixin,
    ArticleMixin,
    ExtendedMetadataHomePageMixin,
    ExtendedMetadataPageMixin,
    MainArticlePageMixin,
    MainArticlesPageMixin,
    MainContactPageMixin,
    MainHomePageMixin,
    MainPeoplePageMixin,
    MainPersonPageMixin,
    MainProgramPageMixin,
    MainSearchPageMixin,
    MainSimplePageMixin,
    PageInMenuMixin,
    SharedTaggedMainArticle,
    SubpageMixin,
)
from shared.utils import make_promote_panels

from . import blocks
from .forms import CareerSubmissionForm, MainArticlesPageForm


class MainHomePage(MainHomePageMixin):
    # content
    content = StreamField(
        [
            ("carousel", blocks.HomePageCarouseSlideBlock()),
            (
                "news",
                shared_blocks.NewsBlock(
                    template="styleguide2/includes/organisms/articles/articles_section.html"
                ),
            ),
            # ("europarl_news", blocks.EuroparlNewsBlock()),
            ("people", shared_blocks.PeopleOverviewBlock()),
            ("regions", blocks.RegionsBlock()),
            ("boxes", blocks.BoxesBlock()),
        ],
        verbose_name="Hlavní obsah",
        blank=True,
        use_json_field=True,
    )

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

    # settings
    gdpr_and_cookies_page = models.ForeignKey(
        "main.MainSimplePage",
        verbose_name="Stránka pro GDPR",
        on_delete=models.PROTECT,
        blank=True,
        null=True,
    )

    subpage_types = [
        "main.MainArticlesPage",
        "main.MainProgramPage",
        "main.MainPeoplePage",
        "main.MainPersonPage",
        "main.MainSimplePage",
        "main.MainContactPage",
        "main.MainCrossroadPage",
        "main.MainHoaxPage",
        "main.MainSearchPage",
        "main.MainResultsPage",
        "main.MainCareersPage",
    ]

    ### OTHERS

    class Meta:
        verbose_name = "HomePage pirati.cz"

    @property
    def careers_page(self):
        return self._first_subpage_of_type(MainCareersPage)

    @property
    def article_page_model(self):
        return MainArticlePage

    @property
    def articles_page_model(self):
        return MainArticlesPage

    @property
    def contact_page_model(self):
        return MainContactPage

    @property
    def search_page_model(self):
        return MainSearchPage

    @property
    def people_page_model(self):
        return MainPeoplePage

    @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 MainArticleTag(TaggedItemBase):
    content_object = ParentalKey(
        "main.MainArticlePage",
        on_delete=models.CASCADE,
        related_name="main_tagged_items",
    )


class MainArticlesPage(MainArticlesPageMixin):
    base_form_class = MainArticlesPageForm

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

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

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


class MainArticlePage(MainArticlePageMixin):
    author_page = models.ForeignKey(
        "main.MainPersonPage",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name="Stránka autora (osoby)",
    )
    tags = ClusterTaggableManager(
        through=MainArticleTag, related_name="main_tagged_articles", blank=True
    )
    shared_tags = ClusterTaggableManager(
        verbose_name="Štítky pro sdílení mezi weby",
        through=SharedTaggedMainArticle,
        blank=True,
    )

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


class MainProgramPage(MainProgramPageMixin):
    ### FIELDS

    program = StreamField(
        [
            ("program_group", shared_blocks.ProgramGroupBlock()),
            ("program_group_crossroad", blocks.ProgramGroupBlockCrossroad()),
            ("program_group_popout", blocks.ProgramGroupBlockPopout()),
            ("program_group_with_candidates", blocks.ProgramGroupWithCandidatesBlock()),
            ("elections_program", blocks.ElectionsProgramBlock()),
        ],
        verbose_name="Programy",
        blank=True,
        use_json_field=True,
    )

    ### RELATIONS

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


class MainPeoplePage(MainPeoplePageMixin):
    content = StreamField(
        [
            ("people_group", blocks.PeopleGroupBlock(label="Seznam osob")),
            ("team_group", blocks.TeamBlock()),
        ],
        verbose_name="Lidé a týmy",
        blank=True,
        use_json_field=True,
    )

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


class MainPersonPage(MainPersonPageMixin):
    ### RELATIONS

    parent_page_types = ["main.MainPeoplePage"]


class MainSimplePage(MainSimplePageMixin):
    parent_page_types = [
        "main.MainHomePage",
        "main.MainSimplePage",
        "main.MainCrossroadPage",
        "main.MainPeoplePage",
    ]
    subpage_types = ["main.MainSimplePage"]


class MainContactPage(MainContactPageMixin):
    ### FIELDS

    contact_people = StreamField(
        [("item", blocks.PersonContactBlock())],
        verbose_name="Kontaktní osoby",
        blank=True,
        use_json_field=True,
    )

    ### RELATIONS

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


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

    headlined_cards_content = StreamField(
        [(("headlined_cards"), blocks.CardLinkWithHeadlineBlock())],
        verbose_name="Karty rozcestníku s nadpisem",
        blank=True,
        use_json_field=True,
    )
    cards_content = StreamField(
        [("cards", blocks.CardLinkBlock())],
        verbose_name="Karty rozcestníku",
        blank=True,
        use_json_field=True,
    )

    ### PANELS

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

    promote_panels = make_promote_panels()

    settings_panels = []

    ### RELATIONS

    parent_page_types = [
        "main.MainHomePage",
        "main.MainCrossroadPage",
    ]
    subpage_types = [
        "main.MainSimplePage",
        "main.MainCrossroadPage",
    ]
    ### OTHERS

    class Meta:
        verbose_name = "Rozcestník s kartami"


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

    description = RichTextField(
        "Popis",
        blank=True,
        null=True,
    )

    content = StreamField(
        [(("hoax"), blocks.HoaxBlock())],
        verbose_name="Hoaxy a jejich vysvětlení",
        blank=True,
        use_json_field=True,
    )

    ### PANELS

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

    promote_panels = make_promote_panels()

    settings_panels = []

    ### RELATIONS

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

    ### OTHERS

    class Meta:
        verbose_name = "Hoaxy"


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

    content = StreamField(
        [
            (("flip_cards"), shared_blocks.FlipCardsBlock()),
            (
                "text",
                RichTextBlock(
                    template="styleguide2/includes/atoms/text/prose_richtext.html"
                ),
            ),
        ],
        verbose_name="Obsah",
        blank=True,
        use_json_field=True,
    )

    ### PANELS

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

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

    class Meta:
        verbose_name = "Výsledky"


class MainCareersPage(
    ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, PageInMenuMixin, Page
):
    subheading = models.CharField(
        verbose_name="Podtitulek",
        help_text="Text pod hlavním nadpisem stránky",
        max_length=32,
        blank=True,
        null=True,
    )

    perex_col_1 = models.TextField(
        verbose_name="Perex - první sloupec",
        blank=True,
        null=True,
    )
    perex_col_2 = models.TextField(
        verbose_name="Perex - druhý sloupec",
        blank=True,
        null=True,
    )

    content_panels = Page.content_panels + [
        HelpPanel(
            "Pro přidání pracovních nabídek ulož tuto stránku a přidej ji podstránky."
        ),
        FieldPanel("subheading"),
        MultiFieldPanel(
            [
                FieldPanel("perex_col_1", heading="První sloupec"),
                FieldPanel("perex_col_2", heading="Druhý sloupec"),
            ],
            "Perex",
        ),
    ]

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

    def get_career_categories(self) -> list[str]:
        return (
            MainCareerPage.objects.child_of(self)
            .live()
            .distinct("category")
            .values_list("category", flat=True)
            .order_by("category")
            .all()
        )

    def get_career_pages(self):
        return MainCareerPage.objects.child_of(self).live().all()

    class Meta:
        verbose_name = "Kariéry"


class MainCareerPage(
    ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, PageInMenuMixin, Page
):
    recipient_emails = models.CharField(
        verbose_name="Příjemci emailů o nových přihláškách",
        help_text="Zadej buď jednu adresu, nebo víc, oddělených čárkami.",
        blank=False,
        null=False,
    )

    category = models.CharField(
        verbose_name="Kategorie pracovní pozice",
        help_text="Např. 'Koordinátor/ka', 'Programátor/ka', 'Volební manažer/ka', ...",
        blank=False,
        null=False,
    )

    location = models.CharField(
        verbose_name="Místo výkonu práce",
        help_text="Např. 'Středočeský kraj'",
        max_length=64,
        blank=False,
        null=False,
    )

    time_cost = models.CharField(
        verbose_name="Časová náročnost",
        help_text="Např. '8h denně'",
        max_length=64,
        blank=False,
        null=False,
    )

    employment_relationship = models.CharField(
        verbose_name="Poměr",
        help_text="Např. 'Rámcová smlouva na dobu určitou'",
        max_length=128,
        blank=False,
        null=False,
    )

    pay_rate = models.CharField(
        verbose_name="Odměna",
        help_text="Např. '300-350 Kč/h'",
        max_length=64,
        blank=False,
        null=False,
    )

    submission_end_date = models.DateField(
        verbose_name="Datum konce přihlášek",
        blank=False,
        null=False,
    )

    created_date = models.DateField(
        verbose_name="Datum vytvoření", blank=False, null=False, default=date.today
    )

    content = RichTextField(
        "Text nabídky", blank=True, features=RICH_TEXT_DEFAULT_FEATURES
    )

    content_panels = Page.content_panels + [
        MultiFieldPanel(
            [
                FieldPanel("submission_end_date"),
                FieldPanel("created_date"),
            ],
            "Datumy",
        ),
        FieldPanel("recipient_emails"),
        FieldPanel("category"),
        FieldPanel("location"),
        FieldPanel("time_cost"),
        FieldPanel("employment_relationship"),
        FieldPanel("pay_rate"),
        FieldPanel("content"),
    ]

    parent_page_types = ["main.MainCareersPage"]

    def serve(self, request):
        form = None
        current_time = datetime.now()

        if request.method == "POST":
            form = CareerSubmissionForm(request.POST, request.FILES)

            if form.is_valid():
                other_files_names = ""

                for file in form.cleaned_data["other_files"]:
                    other_files_names += f"        - {file.name}\n"

                email = EmailMessage(
                    # Subject
                    f"Nová přihláška k pracovní pozici {self.title} - {form.cleaned_data['name']} {form.cleaned_data['surname']}",
                    # Message
                    (
                        f"""
K pracovní pozici {self.title} se {current_time} přihlásil nový zájemce.

Vyplněné údaje:

    Jméno: {form.cleaned_data['name']}
    Příjmení: {form.cleaned_data['surname']}
    E-mail: {form.cleaned_data['email']}
    Telefon: {form.cleaned_data['phone']}
    Vlastní text: {form.cleaned_data['own_text'] if form.cleaned_data['own_text'] else '(nevyplněn)'}

CV, motivační dopis a ostatní soubory jsou v přílohách. Názvy souborů:

    CV: {form.cleaned_data["cv_file"].name}
    Mot. dopis: {form.cleaned_data["cover_letter_file"].name}
    Ostatní soubory:
{other_files_names}

Při otevírání souborů buďte opatrní, virový sken neproběhl!
                        """
                    ),
                    # From email
                    "vyberka@pirati.cz",
                    # Recipient list
                    self.recipient_emails.split(","),
                )

                email.attach(
                    form.cleaned_data["cv_file"].name,
                    form.cleaned_data["cv_file"].read(),
                    form.cleaned_data["cv_file"].content_type,
                )
                email.attach(
                    form.cleaned_data["cover_letter_file"].name,
                    form.cleaned_data["cover_letter_file"].read(),
                    form.cleaned_data["cover_letter_file"].content_type,
                )

                for file in form.cleaned_data["other_files"]:
                    email.attach(file.name, file.read(), file.content_type)

                sent_successfully = email.send(fail_silently=True)

                if sent_successfully:
                    messages.add_message(
                        request, messages.SUCCESS, "Přihláška odeslána."
                    )
                else:
                    messages.add_message(
                        request,
                        messages.ERROR,
                        "Chyba serveru při odesílání přihlášky.",
                    )
            else:
                messages.add_message(
                    request,
                    messages.ERROR,
                    "Chyba při odeslání přihlášky - prohlížeč odeslal chybná data.",
                )
        else:
            form = CareerSubmissionForm()

        return render(
            request,
            self.template,
            {
                "page": self,
                "self": self,
                "form": form,
            },
        )

    class Meta:
        verbose_name = "Pracovní nabídka"


class MainSearchPage(MainSearchPageMixin):
    parent_page_types = ["main.MainHomePage"]
    subpage_types = []

    @property
    def searchable_models(self) -> list:
        return [
            MainArticlePage,
            MainPersonPage,
            MainSimplePage,
        ]