from django.conf import settings
from django.db import models
from django.utils.functional import cached_property
from django.utils.html import format_html_join
from django.utils.translation import gettext_lazy as _

# pylint: disable=E0401,E0611
from oxyan.themes.definitions import theme

from wagtail.admin.panels import (
    FieldPanel,
    FieldRowPanel,
    MultiFieldPanel,
)
from wagtail.contrib.settings.models import BaseSiteSetting, register_setting
from wagtail.search import index

from ocyan.core.fender import config
from ocyan.main.loading import get_ocyan_class, get_ocyan_classes

from .fields import CoyoteStreamField
from .forms import StyleSettingsForm

# pylint: disable=unbalanced-tuple-unpacking
(
    HomePageHeaderStreamBlock,
    HomePageContentStreamBlock,
    HomePageFooterStreamBlock,
    ContactPageHeaderStreamBlock,
    ContactPageContentStreamBlock,
    ContactPageFooterStreamBlock,
) = get_ocyan_classes(
    "coyote.stream_blocks",
    (
        "HomePageHeaderStreamBlock",
        "HomePageContentStreamBlock",
        "HomePageFooterStreamBlock",
        "ContactPageHeaderStreamBlock",
        "ContactPageContentStreamBlock",
        "ContactPageFooterStreamBlock",
    ),
)

AbstractBasePage = get_ocyan_class("ocyan_plugin_wagtail.models", "AbstractBasePage")


@register_setting
class StyleSettings(BaseSiteSetting):
    primary = models.CharField(max_length=7, default=theme["primary"])
    secondary = models.CharField(max_length=7, default=theme["secondary"])
    gray_900 = models.CharField(max_length=7, default=theme["gray-900"])
    gray_200 = models.CharField(max_length=7, default=theme["gray-200"])
    body_color = models.CharField(max_length=7, default=theme["body-color"])
    body_background = models.CharField(max_length=7, default=theme["body-background"])
    footer_background = models.CharField(
        max_length=7, default=theme["footer-background"]
    )
    header_background = models.CharField(
        max_length=7, default=theme["header-background"]
    )
    accent = models.CharField(max_length=7, default=theme["gray-900"])
    text_color = models.CharField(max_length=7, default=theme["body-color"])
    muted_text_color = models.CharField(max_length=7, default=theme["gray-600"])
    surface_background = models.CharField(max_length=7, default=theme["gray-200"])
    border_color = models.CharField(max_length=7, default=theme["gray-300"])
    button_background = models.CharField(max_length=7, default=theme["primary"])
    button_text = models.CharField(max_length=7, default=theme["white"])
    button_hover_background = models.CharField(max_length=7, default=theme["secondary"])
    button_hover_text = models.CharField(max_length=7, default=theme["white"])
    header_text = models.CharField(max_length=7, default=theme["body-color"])
    footer_text = models.CharField(max_length=7, default=theme["body-color"])

    header_font = models.CharField(max_length=255, blank=True, null=True)
    paragraph_font = models.CharField(max_length=255, blank=True, null=True)
    header_font_family = models.CharField(max_length=255, blank=True, null=True)
    paragraph_font_family = models.CharField(max_length=255, blank=True, null=True)
    header_font_variant = models.CharField(max_length=255, default="")
    paragraph_font_variant = models.CharField(max_length=255, default="")

    border_radius = models.DecimalField(
        max_digits=6, decimal_places=2, default=theme["border-radius"]
    )

    header = models.CharField(
        max_length=255,
        null=True,
        choices=settings.OXYAN_HEADER_OPTIONS,
        default=theme.get("header", "basic"),
    )

    panels = [
        MultiFieldPanel(
            (
                FieldRowPanel(
                    (
                        FieldPanel("primary"),
                        FieldPanel("secondary"),
                        FieldPanel("accent"),
                    )
                ),
                FieldRowPanel(
                    (
                        FieldPanel("text_color"),
                        FieldPanel("muted_text_color"),
                        FieldPanel("border_color"),
                    )
                ),
                FieldRowPanel(
                    (
                        FieldPanel("body_background"),
                        FieldPanel("surface_background"),
                        FieldPanel("header_background"),
                    )
                ),
                FieldRowPanel(
                    (
                        FieldPanel("footer_background"),
                        FieldPanel("header_text"),
                        FieldPanel("footer_text"),
                    )
                ),
                FieldRowPanel(
                    (
                        FieldPanel("button_background"),
                        FieldPanel("button_text"),
                    )
                ),
                FieldRowPanel(
                    (
                        FieldPanel("button_hover_background"),
                        FieldPanel("button_hover_text"),
                    )
                ),
            ),
            heading=_("Colors"),
            classname="collapsed",
        ),
        MultiFieldPanel(
            (
                FieldRowPanel(
                    (
                        FieldPanel("header_font_family"),
                        FieldPanel("header_font_variant"),
                        FieldPanel("paragraph_font_family"),
                        FieldPanel("paragraph_font_variant"),
                    ),
                    classname="fontpanel",
                ),
                FieldRowPanel(
                    (
                        FieldPanel("header_font"),
                        FieldPanel("paragraph_font"),
                    )
                ),
            ),
            heading=_("Typography"),
            classname="collapsed",
        ),
        MultiFieldPanel(
            (
                FieldPanel("border_radius"),
                # Do not display the header options if they are not available
                *([FieldPanel("header")] if settings.OXYAN_HEADER_OPTIONS else []),
            ),
            heading=_("General"),
            classname="collapsed",
        ),
    ]

    @cached_property
    def definitions(self):
        basket_counter_background = config.get(
            "themes", "basket-counter-background", self.primary
        )
        header_font_family = (
            [f'"{self.header_font_family}"', "sans-serif"]
            if self.header_font_family
            else None
        )
        paragraph_font_family = (
            [f'"{self.paragraph_font_family}"', "sans-serif"]
            if self.paragraph_font_family
            else None
        )

        return {
            # colors
            "primary": self.primary,
            "secondary": self.secondary,
            "accent": self.accent,
            "text-color": self.text_color,
            "muted-text-color": self.muted_text_color,
            "surface-background": self.surface_background,
            "border-color": self.border_color,
            "button-background": self.button_background,
            "button-text": self.button_text,
            "button-hover-background": self.button_hover_background,
            "button-hover-text": self.button_hover_text,
            "header-text": self.header_text,
            "footer-text": self.footer_text,
            # legacy aliases kept for compatibility
            "gray-900": self.accent,
            "gray-200": self.surface_background,
            "body-color": self.text_color,
            "body-background": self.body_background,
            "footer-background": self.footer_background,
            "header-background": self.header_background,
            "basket-counter-background": basket_counter_background,
            # font
            "header-font-family": header_font_family,
            "font-family-sans-serif": paragraph_font_family,
            "font-weight-headers": (
                "700" if "bold" in self.header_font_variant else "400"
            ),
            "font-weight-normal": (
                "700" if "bold" in self.paragraph_font_variant else "400"
            ),
            "headings-font-style": (
                "italic" if "italic" in self.header_font_variant else "normal"
            ),
            "border-radius": self.border_radius,
            "header": self.header,
        }

    @cached_property
    def runtime_css_variables(self):
        return {
            "--coyote-primary": self.primary,
            "--coyote-secondary": self.secondary,
            "--coyote-accent": self.accent,
            "--coyote-text-color": self.text_color,
            "--coyote-muted-text-color": self.muted_text_color,
            "--coyote-background": self.body_background,
            "--coyote-surface-background": self.surface_background,
            "--coyote-border-color": self.border_color,
            "--coyote-button-background": self.button_background,
            "--coyote-button-text": self.button_text,
            "--coyote-button-hover-background": self.button_hover_background,
            "--coyote-button-hover-text": self.button_hover_text,
            "--coyote-header-background": self.header_background,
            "--coyote-header-text": self.header_text,
            "--coyote-footer-background": self.footer_background,
            "--coyote-footer-text": self.footer_text,
            "--coyote-border-radius": str(self.border_radius),
        }

    @cached_property
    def runtime_css(self):
        css_variables = format_html_join(
            "",
            "{}:{};",
            ((name, value) for name, value in self.runtime_css_variables.items()),
        )
        return (
            ".coyote-outer{"
            f"{css_variables}"
            "}"
            ".coyote-outer:not(.monochrome) .coyote-wrapper>div:nth-child(3n-2)>section,"
            ".coyote-outer:not(.monochrome) .coyote-wrapper>div>section.background_body{"
            "background:var(--coyote-background);"
            "color:var(--coyote-text-color)!important;"
            "--icon-block-background:var(--coyote-button-background);"
            "--icon-block-color:var(--coyote-button-text);"
            "--icon-block-background-hover:var(--coyote-button-hover-background);"
            "--icon-block-color-hover:var(--coyote-button-hover-text);"
            "--counter-color:var(--coyote-text-color);"
            "--contrast-color:var(--coyote-accent);"
            "--background:var(--coyote-background);"
            "}"
            ".coyote-outer:not(.monochrome) .coyote-wrapper>div:nth-child(3n-1)>section,"
            ".coyote-outer:not(.monochrome) .coyote-wrapper>div>section.dark{"
            "background:var(--coyote-accent);"
            "color:var(--coyote-footer-text)!important;"
            "--icon-block-background:var(--coyote-surface-background);"
            "--icon-block-color:var(--coyote-text-color);"
            "--icon-block-background-hover:var(--coyote-button-background);"
            "--icon-block-color-hover:var(--coyote-button-text);"
            "--counter-color:var(--coyote-footer-text);"
            "--contrast-color:var(--coyote-surface-background);"
            "--background:var(--coyote-accent);"
            "}"
            ".coyote-outer:not(.monochrome) .coyote-wrapper>div:nth-child(3n)>section,"
            ".coyote-outer:not(.monochrome) .coyote-wrapper>div>section.light,"
            ".coyote-outer.monochrome section{"
            "background:var(--coyote-surface-background);"
            "color:var(--coyote-text-color)!important;"
            "--icon-block-background:var(--coyote-button-background);"
            "--icon-block-color:var(--coyote-button-text);"
            "--icon-block-background-hover:var(--coyote-button-hover-background);"
            "--icon-block-color-hover:var(--coyote-button-hover-text);"
            "--counter-color:var(--coyote-text-color);"
            "--contrast-color:var(--coyote-accent);"
            "--background:var(--coyote-surface-background);"
            "}"
            ".coyote-outer .btn-primary{"
            "background:var(--coyote-button-background);"
            "border-color:var(--coyote-button-background);"
            "color:var(--coyote-button-text);"
            "}"
            ".coyote-outer .btn-primary:hover,"
            ".coyote-outer .btn-primary:focus{"
            "background:var(--coyote-button-hover-background);"
            "border-color:var(--coyote-button-hover-background);"
            "color:var(--coyote-button-hover-text);"
            "}"
            ".coyote-outer .btn-outline-primary{"
            "border-color:var(--coyote-button-background);"
            "color:var(--coyote-button-background);"
            "}"
            ".coyote-outer .btn-outline-primary:hover,"
            ".coyote-outer .btn-outline-primary:focus{"
            "background:var(--coyote-button-background);"
            "border-color:var(--coyote-button-background);"
            "color:var(--coyote-button-text);"
            "}"
            ".coyote-outer .hero.content{background:var(--coyote-surface-background);}"
            ".coyote-outer .hero.full-screen.video.layout2 .hero-lead .rich-text *{"
            "color:var(--coyote-text-color);"
            "}"
            "body:has(.coyote-outer .hero--transparent-header) header{"
            "position:absolute;"
            "top:0;"
            "left:0;"
            "width:100%;"
            "background:transparent;"
            "z-index:9999;"
            "}"
            "body:has(.coyote-outer .hero--transparent-header) header nav.navbar{"
            "background:transparent;"
            "}"
            "body:has(.coyote-outer .hero--inverse-header) header .navbar-brand{"
            "filter:brightness(0) invert(1);"
            "}"
            "body:has(.coyote-outer .hero--inverse-header) header .header-inner .menu-bar>ul>.nav-item>.nav-link,"
            "body:has(.coyote-outer .hero--inverse-header) header .header-inner .menu-bar .nav-item .nav-link,"
            "body:has(.coyote-outer .hero--inverse-header) header .header-inner .nav-icon{"
            "color:var(--coyote-button-text);"
            "}"
            ".coyote-outer .hero.full-screen svg path{fill:var(--coyote-background);}"
            ".coyote-outer .hero.full-screen svg .hero-wave-shadow{"
            "fill:var(--coyote-border-color);"
            "}"
            ".coyote-outer .hero.full-screen svg .hero-wave-shadow-alt{"
            "fill:var(--coyote-surface-background);"
            "}"
            ".coyote-outer .hero.full-screen svg .hero-wave-main{"
            "fill:var(--coyote-background);"
            "}"
            ".coyote-outer .tabs .tab-style-1 ul button.active{"
            "border-bottom-color:var(--coyote-primary);"
            "}"
            ".coyote-outer .call_to_action{"
            "background:linear-gradient(to bottom, transparent 11rem, var(--coyote-footer-background) 11rem);"
            "}"
            ".coyote-outer .call_to_action>.container .container-inner,"
            ".coyote-outer .call_to_action>.container>i{"
            "background:var(--coyote-button-background);"
            "color:var(--coyote-button-text);"
            "}"
            ".coyote-outer .info-block-wrapper{"
            "background-color:var(--coyote-footer-background);"
            "color:var(--coyote-footer-text);"
            "}"
            ".coyote-outer .info-block-wrapper .blokje-info:hover{"
            "border-color:var(--coyote-footer-text);"
            "}"
            ".coyote-outer .content-wrapper .content-image-text p{"
            "color:var(--coyote-muted-text-color);"
            "}"
            ".coyote-outer .content-wrapper .content-image-text .btn-primary{"
            "border-radius:var(--coyote-border-radius);"
            "}"
            ".coyote-outer .contact_form .coyote-inline-form-fields{"
            "display:flex;"
            "flex-flow:row wrap;"
            "gap:2rem;"
            "}"
            ".coyote-outer .contact_form .coyote_field--inline{"
            "display:flex;"
            "flex-wrap:wrap;"
            "user-select:none;"
            "}"
            ".coyote-outer .contact_form .coyote_field__label--inline{"
            "width:100%;"
            "padding:0 0 0 5px;"
            "}"
            ".coyote-outer .contact_form #contact-form label{"
            "color:var(--coyote-text-color);"
            "}"
            ".coyote-outer .contact_form #contact-form input:not([type='submit']),"
            ".coyote-outer .contact_form #contact-form textarea{"
            "color:var(--coyote-text-color);"
            "}"
            ".coyote-outer .contact_form #contact-form .form_field_wrapper .form-control{"
            "border-bottom-color:var(--coyote-border-color);"
            "background:transparent;"
            "}"
            ".coyote-outer .coyote-category-block .rich-text h1 i,"
            ".coyote-outer .coyote-category-block .rich-text h2 i,"
            ".coyote-outer .coyote-category-block .rich-text h3 i,"
            ".coyote-outer .coyote-category-block .rich-text h4 i,"
            ".coyote-outer .products-block .rich-text h1 i,"
            ".coyote-outer .products-block .rich-text h2 i,"
            ".coyote-outer .products-block .rich-text h3 i,"
            ".coyote-outer .products-block .rich-text h4 i{"
            "color:var(--coyote-primary);"
            "}"
            "header nav.navbar{"
            "background:var(--coyote-header-background);"
            "color:var(--coyote-header-text);"
            "}"
            ".footer{"
            "background:var(--coyote-footer-background);"
            "color:var(--coyote-footer-text);"
            "}"
        )

    def save(self, *args, **kwargs):
        self.gray_900 = self.accent
        self.gray_200 = self.surface_background
        self.body_color = self.text_color
        super().save(*args, **kwargs)

    class Meta:
        verbose_name = "Template page settings"

    base_form_class = StyleSettingsForm


class CoyoteHomePage(AbstractBasePage):
    template = "coyote/pages/home.html"

    header = CoyoteStreamField(
        HomePageHeaderStreamBlock(),
        blank=True,
        verbose_name="Header",
        max_num=1,
        use_json_field=True,
    )
    content = CoyoteStreamField(
        HomePageContentStreamBlock(),
        blank=True,
        verbose_name=_("Content"),
        collapsed=True,
        use_json_field=True,
    )
    footer = CoyoteStreamField(
        HomePageFooterStreamBlock(),
        blank=True,
        verbose_name="Footer",
        max_num=1,
        use_json_field=True,
    )

    content_panels = AbstractBasePage.content_panels + [
        FieldPanel("header", classname="collapsible"),
        FieldPanel("content", classname="collapsible"),
        FieldPanel("footer", classname="collapsible"),
    ]

    search_fields = AbstractBasePage.search_fields + [
        index.SearchField("header", partial_match=True),
        index.SearchField("content", partial_match=True),
        index.SearchField("footer", partial_match=True),
    ]

    page_description = _(
        "Predefined layout that ensures your content always looks good."
    )

    class Meta:
        verbose_name = "Template page"


class CoyoteContactPage(AbstractBasePage):
    is_creatable = "ocyan.plugin.contact_form" in config.ocyan_plugins
    template = "coyote/pages/contact.html"

    header = CoyoteStreamField(
        ContactPageHeaderStreamBlock(),
        blank=True,
        verbose_name="Header",
        max_num=1,
        use_json_field=True,
    )
    content = CoyoteStreamField(
        ContactPageContentStreamBlock(),
        blank=True,
        verbose_name=_("Content"),
        use_json_field=True,
    )
    footer = CoyoteStreamField(
        ContactPageFooterStreamBlock(),
        blank=True,
        verbose_name="Footer",
        max_num=1,
        use_json_field=True,
    )

    content_panels = AbstractBasePage.content_panels + [
        FieldPanel("header", classname="collapsible"),
        FieldPanel("content", classname="collapsible"),
        FieldPanel("footer", classname="collapsible"),
    ]

    search_fields = AbstractBasePage.search_fields + [
        index.SearchField("header", partial_match=True),
        index.SearchField("content", partial_match=True),
        index.SearchField("footer", partial_match=True),
    ]

    page_description = _(
        "Predefined layout that ensures your contact page always looks good."
    )

    class Meta:
        verbose_name = "Contact template page"
