from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator
from django.db import models
from wagtail.admin.panels import FieldPanel
from wagtail.api import APIField
from wagtail.blocks import ChoiceBlock, StructBlock, StructValue, URLBlock
from wagtail.fields import StreamField
from wagtail.models import Page
from wagtail.search import index

from bakerydemo.base.blocks import BaseStreamBlock

from ..breads.models import Country


class SocialMediaValue(StructValue):
    def get_platform_label(self):
        return dict(self.block.child_blocks["platform"].field.choices).get(
            self["platform"]
        )


class SocialMediaBlock(StructBlock):
    """
    Block for social media links
    """

    platform = ChoiceBlock(
        choices=[
            ("github", "GitHub"),
            ("twitter", "Twitter/X"),
            ("linkedin", "LinkedIn"),
            ("instagram", "Instagram"),
            ("facebook", "Facebook"),
            ("mastodon", "Mastodon"),
            ("website", "Personal Website"),
        ],
        help_text="Select the social media platform",
    )
    url = URLBlock(
        label="URL",
        help_text="Full URL to your profile (e.g., https://github.com/username)",
    )

    class Meta:
        icon = "link"
        label = "Social Media Link"
        value_class = SocialMediaValue


class PersonPage(Page):
    """
    Detail view for a specific person
    """

    introduction = models.TextField(help_text="Text to describe the page", blank=True)
    image = models.ForeignKey(
        "wagtailimages.Image",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
        help_text="Landscape mode only; horizontal width between 1000px and 3000px.",
    )
    body = StreamField(BaseStreamBlock(), verbose_name="Page body", blank=True)

    location = models.ForeignKey(
        Country,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
    )

    social_links = StreamField(
        [("social", SocialMediaBlock())],
        blank=True,
        help_text="Add social media profiles",
    )

    content_panels = Page.content_panels + [
        FieldPanel("introduction"),
        FieldPanel("image"),
        FieldPanel("location"),
        FieldPanel("body"),
        FieldPanel("social_links"),
    ]

    search_fields = Page.search_fields + [
        index.SearchField("introduction"),
        index.SearchField("body"),
    ]

    parent_page_types = ["PeopleIndexPage"]

    api_fields = [
        APIField("introduction"),
        APIField("image"),
        APIField("body"),
        APIField("location"),
        APIField("social_links"),
    ]

    def get_context(self, request):
        context = super(PersonPage, self).get_context(request)

        platform_block = SocialMediaBlock().child_blocks["platform"]
        platform_labels = dict(platform_block.field.choices)
        social_links = [
            {
                "platform": link.value["platform"],
                "label": platform_labels.get(
                    link.value["platform"], link.value["platform"]
                ),
                "url": link.value["url"],
            }
            for link in (self.social_links or [])
        ]

        context["social_links"] = social_links

        return context


class PeopleIndexPage(Page):
    """
    Index page for people.

    Lists all People objects with pagination.
    """

    introduction = models.TextField(help_text="Text to describe the page", blank=True)
    image = models.ForeignKey(
        "wagtailimages.Image",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
        help_text="Landscape mode only; horizontal width between 1000px and 3000px.",
    )

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

    # Can only have PersonPage children
    subpage_types = ["PersonPage"]

    api_fields = [
        APIField("introduction"),
        APIField("image"),
    ]

    # Returns a queryset of PersonPage objects that are live, that are direct
    # descendants of this index page with most recent first
    def get_people(self):
        return (
            PersonPage.objects.live()
            .descendant_of(self)
            .order_by("-first_published_at")
        )

    # Allows child objects (e.g. PersonPage objects) to be accessible via the
    # template
    def children(self):
        return self.get_children().specific().live()

    # Pagination for the index page
    def paginate(self, request, *args):
        page = request.GET.get("page")
        paginator = Paginator(self.get_people(), 12)
        try:
            pages = paginator.page(page)
        except PageNotAnInteger:
            pages = paginator.page(1)
        except EmptyPage:
            pages = paginator.page(paginator.num_pages)
        return pages

    # Returns the above to the get_context method that is used to populate the
    # template
    def get_context(self, request):
        context = super(PeopleIndexPage, self).get_context(request)

        # PersonPage objects (get_people) are passed through pagination
        people = self.paginate(request, self.get_people())

        context["people"] = people

        return context
