from django.db import models
from django.utils.safestring import mark_safe
from grapple.helpers import register_query_field, register_streamfield_block
from grapple.models import GraphQLForeignKey, GraphQLStreamfield, GraphQLString
from modelcluster.fields import ParentalKey
from modelcluster.models import ClusterableModel
from wagtail import blocks
from wagtail.admin.panels import FieldPanel, InlinePanel, MultiFieldPanel, TitleFieldPanel
from wagtail.fields import StreamField
from wagtail.models import Orderable
from wagtail.snippets.models import register_snippet


@register_streamfield_block
class OpeningHoursRangeBlock(blocks.StructBlock):
    time_from = blocks.TimeBlock(required=False, label="Åpner")
    time_to = blocks.TimeBlock(required=False, label="Stenger")
    custom = blocks.CharBlock(
        required=False,
        label="Fritekst",
        help_text=mark_safe(
            "Tekst som vises istedenfor tidspunkter. F.eks. <em>Åpent ved arrangement</em>"
        ),
    )

    graphql_fields = [
        GraphQLString("time_from", required=False),
        GraphQLString("time_to", required=False),
        GraphQLString("custom", required=False),
    ]


@register_streamfield_block
class OpeningHoursWeekBlock(blocks.StructBlock):
    monday = OpeningHoursRangeBlock(label="Mandag")
    tuesday = OpeningHoursRangeBlock(label="Tirsdag")
    wednesday = OpeningHoursRangeBlock(label="Onsdag")
    thursday = OpeningHoursRangeBlock(label="Torsdag")
    friday = OpeningHoursRangeBlock(label="Fredag")
    saturday = OpeningHoursRangeBlock(label="Lørdag")
    sunday = OpeningHoursRangeBlock(label="Søndag")

    graphql_fields = [
        GraphQLStreamfield("monday", required=False, is_list=False),
        GraphQLStreamfield("tuesday", required=False, is_list=False),
        GraphQLStreamfield("wednesday", required=False, is_list=False),
        GraphQLStreamfield("thursday", required=False, is_list=False),
        GraphQLStreamfield("friday", required=False, is_list=False),
        GraphQLStreamfield("saturday", required=False, is_list=False),
        GraphQLStreamfield("sunday", required=False, is_list=False),
    ]


class OpeningHoursItem(Orderable):
    FUNCTION_CHOICES = [
        ("glassbaren", "Glassbaren"),
        ("bokcafeen", "Bokcaféen"),
        ("ekspedisjonen", "Ekspedisjonen"),
    ]
    WEEKDAYS = (
        ("monday", "Mandag"),
        ("tuesday", "Tirsdag"),
        ("wednesday", "Onsdag"),
        ("thursday", "Torsdag"),
        ("friday", "Fredag"),
        ("saturday", "Lørdag"),
        ("sunday", "Søndag"),
    )

    opening_hours_set = ParentalKey(
        "openinghours.OpeningHoursSet", on_delete=models.CASCADE, related_name="items"
    )
    function = models.CharField(
        max_length=32,
        default="",
        choices=FUNCTION_CHOICES,
        blank=False,
        help_text="Hvilket lokale/funksjon?",
    )

    week = StreamField(
        [("week", OpeningHoursWeekBlock())],
        min_num=1,
        max_num=1,
    )

    panels = [
        FieldPanel("function"),
        FieldPanel("week"),
    ]

    graphql_fields = [
        GraphQLString("function", required=True),
        GraphQLStreamfield("week", required=False),
    ]


@register_snippet
@register_query_field("openingHoursSet", "openingHoursSets")
class OpeningHoursSet(ClusterableModel):
    name = models.CharField(
        max_length=256,
        null=False,
        blank=False,
        help_text=mark_safe(
            "Enkel beskrivelse av hvilken periode disse åpningstidene dekker, "
            "f.eks. <em>Vanlige åpningstider</em> eller <em>Sommer 2032</em>."
        ),
    )
    effective_from = models.DateField(null=False, blank=False)
    effective_to = models.DateField(null=True, blank=True)

    announcement = models.TextField(
        blank=True,
        help_text=mark_safe(
            "En kort notis som vil vises i forbindelse med åpningstidene, "
            "f.eks. <em>Huset er stengt i perioden A til B.</em>. Kan være blank."
        ),
    )

    panels = [
        TitleFieldPanel("name"),
        FieldPanel("announcement"),
        MultiFieldPanel(
            heading="Gyldighet",
            children=[
                FieldPanel("effective_from", heading="Fra"),
                FieldPanel("effective_to", heading="Til"),
            ],
        ),
        InlinePanel("items", label="Lokaler/funksjoner"),
    ]

    graphql_fields = [
        GraphQLString("name", required=True),
        GraphQLString("announcement", required=False),
        GraphQLString("effective_from", required=True),
        GraphQLString("effective_to", required=False),
        GraphQLForeignKey("items", "openinghours.OpeningHoursItem", required=False, is_list=True),
    ]

    class Meta:
        verbose_name = "Opening hours set"
        verbose_name_plural = "Opening hours sets"
        ordering = ["effective_from"]

    def __str__(self):
        return f"{self.name} ({self.effective_from} - {self.effective_to or '∞'})"
