from django import forms as django_forms
from django.db import models
from django.utils.translation import gettext_lazy as _
from wagtail.admin.panels import (
    FieldPanel,
    MultiFieldPanel,
    
    # import PublishingPanel:
    PublishingPanel,
)

# import RichTextField:
from wagtail.fields import RichTextField

# import DraftStateMixin, PreviewableMixin, RevisionMixin, TranslatableMixin:
from wagtail.models import (
    DraftStateMixin,
    PreviewableMixin,
    RevisionMixin,
    TranslatableMixin,
)

from wagtail.contrib.settings.models import (
    BaseGenericSetting,
    register_setting,
)

from wagtail.snippets.models import register_snippet
from wagtail.fields import StreamField
from wagtail import blocks

from .security import encrypt_text


@register_setting
class HeaderSettings(BaseGenericSetting):
    logo_light = models.ForeignKey(
        "wagtailimages.Image",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
        help_text=_("Use on dark background (light logo)."),
        verbose_name=_("Light Logo"),
    )
    logo_dark = models.ForeignKey(
        "wagtailimages.Image",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
        help_text=_("Use on light background (dark logo)."),
        verbose_name=_("Dark Logo"),
    )
    site_name = models.CharField(max_length=255, blank=True, verbose_name=_("Site Name"))
    extra_links = StreamField([
        ("link", blocks.StructBlock([
            ("label", blocks.CharBlock(label=_("Label"))),
            ("url", blocks.URLBlock(label=_("URL")))
        ]))
    ], use_json_field=True, blank=True, null=True, verbose_name=_("Extra Links"))

    panels = [
        MultiFieldPanel(
            [
                FieldPanel("logo_light"),
                FieldPanel("logo_dark"),
                FieldPanel("site_name"),
                FieldPanel("extra_links"),
            ],
            heading=_("Header Settings"),
        ),
    ]

    class Meta:
        verbose_name = _("Header Settings")

@register_setting
class NavigationSettings(BaseGenericSetting):
    footer_links = StreamField([
        ("section", blocks.StructBlock([
            ("title", blocks.CharBlock(required=False, label=_("Section Title"))),
            ("links", blocks.ListBlock(blocks.StructBlock([
                ("label", blocks.CharBlock(label=_("Label"))),
                ("url", blocks.URLBlock(label=_("URL")))
            ]))),
        ]))
    ], use_json_field=True, blank=True, null=True, verbose_name=_("Footer Links"))
    
    panels = [
        FieldPanel("footer_links"),
    ]

    class Meta:
        verbose_name = _("Footer Navigation")

class SocialLinkBlock(blocks.StructBlock):
    SOCIAL_MEDIA_CHOICES = [
                ("facebook", _("Facebook")),
                ("twitter", _("Twitter")),
                ("instagram", _("Instagram")),
                ("threads", _("Threads")),
                ("linkedin", _("LinkedIn")),
                ("youtube", _("YouTube")),
            ]
    
    platform = blocks.ChoiceBlock(choices=SOCIAL_MEDIA_CHOICES, label=_("Platform"))
    url = blocks.URLBlock(label=_("URL"))

    class Meta:
        icon = "link"
        label = _("Social Link")

@register_setting
class SocialMediaSettings(BaseGenericSetting):
    links = StreamField([
        ("link", SocialLinkBlock()),
    ], use_json_field=True, verbose_name=_("Social Links"))

    panels = [FieldPanel("links")]

    class Meta:
        verbose_name = _("Social Media Settings")


@register_setting
class MailSmtpSettings(BaseGenericSetting):
    smtp_relay_host = models.CharField(max_length=255, blank=True, verbose_name=_("SMTP Relay Host"))
    smtp_relay_port = models.PositiveIntegerField(default=587, verbose_name=_("SMTP Relay Port"))
    smtp_use_tls = models.BooleanField(default=True, verbose_name=_("Use TLS"))
    smtp_use_ssl = models.BooleanField(
        default=False,
        help_text=_("Port 465 usually uses SSL (Implicit TLS); port 587 usually uses STARTTLS (TLS)."),
        verbose_name=_("Use SSL"),
    )
    smtp_timeout_seconds = models.PositiveIntegerField(default=15, verbose_name=_("SMTP Timeout Seconds"))
    smtp_username = models.CharField(max_length=255, blank=True, verbose_name=_("SMTP Username"))
    smtp_password = models.TextField(blank=True, verbose_name=_("SMTP Password"))

    panels = [
        MultiFieldPanel(
            [
                FieldPanel("smtp_relay_host"),
                FieldPanel("smtp_relay_port"),
                FieldPanel("smtp_use_tls"),
                FieldPanel("smtp_use_ssl"),
                FieldPanel("smtp_timeout_seconds"),
                FieldPanel("smtp_username"),
                FieldPanel(
                    "smtp_password",
                    widget=django_forms.PasswordInput(render_value=False),
                ),
            ],
            heading=_("SMTP Settings"),
        ),
    ]

    class Meta:
        verbose_name = _("SMTP Settings")

    def save(self, *args, **kwargs):
        if self.smtp_use_tls and self.smtp_use_ssl:
            raise ValueError("smtp_use_tls and smtp_use_ssl cannot both be True.")

        if self.pk and not self.smtp_password:
            previous = type(self).objects.filter(pk=self.pk).only("smtp_password").first()
            self.smtp_password = previous.smtp_password if previous else ""
        elif self.smtp_password:
            self.smtp_password = encrypt_text(self.smtp_password)

        super().save(*args, **kwargs)


@register_setting
class ContactFormSettings(BaseGenericSetting):
    rate_limit_enabled = models.BooleanField(default=True, verbose_name=_("Enable IP Rate Limit"))
    rate_limit_max_submissions = models.PositiveIntegerField(
        default=3,
        verbose_name=_("Maximum Submissions Per Window"),
    )
    rate_limit_window_minutes = models.PositiveIntegerField(
        default=10,
        verbose_name=_("Rate Limit Window Minutes"),
    )
    send_user_copy = models.BooleanField(
        default=False,
        help_text=_("Send a copy to the submitter only after spam detection allows the message."),
        verbose_name=_("Send User Copy"),
    )

    panels = [
        MultiFieldPanel(
            [
                FieldPanel("rate_limit_enabled"),
                FieldPanel("rate_limit_max_submissions"),
                FieldPanel("rate_limit_window_minutes"),
            ],
            heading=_("Contact Form Rate Limit"),
        ),
        FieldPanel("send_user_copy"),
    ]

    class Meta:
        verbose_name = _("Contact Form Settings")


@register_setting
class NewsletterSystemSettings(BaseGenericSetting):
    member_center_base_url = models.URLField(blank=True, verbose_name=_("Member Center Base URL"))
    member_center_subscribe_path = models.CharField(
        max_length=255,
        blank=True,
        default="/newsletter/subscribe",
        verbose_name=_("Subscribe Path"),
    )
    member_center_confirm_path = models.CharField(
        max_length=255,
        blank=True,
        default="/newsletter/confirm",
        verbose_name=_("Confirm Path"),
    )
    member_center_unsubscribe_token_path = models.CharField(
        max_length=255,
        blank=True,
        default="/newsletter/unsubscribe-token",
        verbose_name=_("Unsubscribe Token Path"),
    )
    member_center_unsubscribe_path = models.CharField(
        max_length=255,
        blank=True,
        default="/newsletter/unsubscribe",
        verbose_name=_("Unsubscribe Path"),
    )
    member_center_subscriptions_path = models.CharField(
        max_length=255,
        blank=True,
        default="/newsletter/subscriptions",
        verbose_name=_("Subscriptions Path"),
    )
    member_center_oauth_token_path = models.CharField(
        max_length=255,
        blank=True,
        default="/oauth/token",
        help_text=_("Shared Member Center OAuth token endpoint path for tenant_api and send_api clients."),
        verbose_name=_("OAuth Token Path"),
    )
    member_center_oauth_client_id = models.CharField(
        max_length=255,
        blank=True,
        help_text=_("Member Center OAuth client_id for usage=tenant_api."),
        verbose_name=_("OAuth Client ID"),
    )
    member_center_oauth_client_secret = models.TextField(
        blank=True,
        help_text=_("Member Center OAuth client_secret for usage=tenant_api."),
        verbose_name=_("OAuth Client Secret"),
    )
    member_center_oauth_scope = models.CharField(
        max_length=255,
        blank=True,
        default="newsletter:list.read",
        verbose_name=_("OAuth Scope"),
    )
    member_center_oauth_audience = models.CharField(max_length=255, blank=True, verbose_name=_("OAuth Audience"))
    member_center_one_click_unsubscribe_path = models.CharField(
        max_length=255,
        blank=True,
        default="/api/subscriptions/unsubscribe",
        verbose_name=_("One-Click Unsubscribe Path"),
    )
    member_center_tenant_id = models.CharField(max_length=128, blank=True, verbose_name=_("Tenant ID"))
    member_center_list_id = models.CharField(max_length=128, blank=True, verbose_name=_("List ID"))
    member_center_timeout_seconds = models.PositiveIntegerField(default=10, verbose_name=_("Member Center Timeout Seconds"))

    send_engine_base_url = models.URLField(blank=True, verbose_name=_("Send Engine Base URL"))
    send_engine_send_jobs_path = models.CharField(
        max_length=255,
        blank=True,
        default="/api/send-jobs",
        verbose_name=_("Send Jobs Path"),
    )
    send_engine_oauth_client_id = models.CharField(
        max_length=255,
        blank=True,
        help_text=_("Member Center OAuth client_id for usage=send_api. Uses the Member Center OAuth Token Path."),
        verbose_name=_("Send Engine OAuth Client ID"),
    )
    send_engine_oauth_client_secret = models.TextField(
        blank=True,
        help_text=_("Member Center OAuth client_secret for usage=send_api. Uses the Member Center OAuth Token Path."),
        verbose_name=_("Send Engine OAuth Client Secret"),
    )
    send_engine_oauth_scope = models.CharField(max_length=255, blank=True, verbose_name=_("Send Engine OAuth Scope"))
    send_engine_timeout_seconds = models.PositiveIntegerField(default=10, verbose_name=_("Send Engine Timeout Seconds"))
    send_engine_retry_interval_seconds = models.PositiveIntegerField(default=300, verbose_name=_("Retry Interval Seconds"))
    send_engine_retry_max_attempts = models.PositiveIntegerField(default=3, verbose_name=_("Retry Max Attempts"))

    sender_name = models.CharField(max_length=255, blank=True, verbose_name=_("Sender Name"))
    sender_email = models.EmailField(blank=True, verbose_name=_("Sender Email"))
    reply_to_email = models.EmailField(blank=True, verbose_name=_("Reply-To Email"))
    default_charset = models.CharField(max_length=50, default="utf-8", verbose_name=_("Default Charset"))
    one_click_endpoint_path = models.CharField(
        max_length=255,
        blank=True,
        default="/u/unsubscribe",
        verbose_name=_("One-Click Endpoint Path"),
    )
    one_click_token_secret = models.CharField(
        max_length=255,
        blank=True,
        help_text=_("One-click token signing secret. Leave blank to use Django SECRET_KEY."),
        verbose_name=_("One-Click Token Secret"),
    )
    one_click_token_ttl_seconds = models.PositiveIntegerField(default=60 * 60 * 24 * 30, verbose_name=_("One-Click Token TTL Seconds"))
    site_base_url = models.URLField(
        blank=True,
        help_text=_("Site base URL for scheduler sends, e.g. https://news.example.com"),
        verbose_name=_("Site Base URL"),
    )

    panels = [
        MultiFieldPanel(
            [
                FieldPanel("member_center_base_url"),
                FieldPanel("member_center_subscribe_path"),
                FieldPanel("member_center_confirm_path"),
                FieldPanel("member_center_unsubscribe_token_path"),
                FieldPanel("member_center_unsubscribe_path"),
                FieldPanel("member_center_subscriptions_path"),
                FieldPanel("member_center_oauth_token_path"),
                FieldPanel("member_center_oauth_client_id"),
                FieldPanel(
                    "member_center_oauth_client_secret",
                    widget=django_forms.PasswordInput(render_value=False),
                ),
                FieldPanel("member_center_one_click_unsubscribe_path"),
                FieldPanel("member_center_tenant_id"),
                FieldPanel("member_center_list_id"),
                FieldPanel("member_center_timeout_seconds"),
            ],
            heading=_("Member Center"),
        ),
        MultiFieldPanel(
            [
                FieldPanel("send_engine_base_url"),
                FieldPanel("send_engine_send_jobs_path"),
                FieldPanel("send_engine_oauth_client_id"),
                FieldPanel(
                    "send_engine_oauth_client_secret",
                    widget=django_forms.PasswordInput(render_value=False),
                ),
                FieldPanel("send_engine_timeout_seconds"),
                FieldPanel("send_engine_retry_interval_seconds"),
                FieldPanel("send_engine_retry_max_attempts"),
            ],
            heading=_("Send Engine"),
        ),
        MultiFieldPanel(
            [
                FieldPanel("one_click_endpoint_path"),
                FieldPanel("one_click_token_secret"),
                FieldPanel("one_click_token_ttl_seconds"),
                FieldPanel("site_base_url"),
            ],
            heading=_("List-Unsubscribe One-Click"),
        ),
        MultiFieldPanel(
            [
                FieldPanel("sender_name"),
                FieldPanel("sender_email"),
                FieldPanel("reply_to_email"),
                FieldPanel("default_charset"),
            ],
            heading=_("Newsletter Mail"),
        ),
    ]

    class Meta:
        verbose_name = _("Newsletter System Settings")

    def save(self, *args, **kwargs):
        previous = None
        if self.pk:
            previous = type(self).objects.filter(pk=self.pk).only(
                "member_center_oauth_client_secret",
                "send_engine_oauth_client_secret",
            ).first()

        if self.pk and not self.member_center_oauth_client_secret:
            self.member_center_oauth_client_secret = previous.member_center_oauth_client_secret if previous else ""
        elif self.member_center_oauth_client_secret:
            self.member_center_oauth_client_secret = encrypt_text(self.member_center_oauth_client_secret)

        if self.pk and not self.send_engine_oauth_client_secret:
            self.send_engine_oauth_client_secret = previous.send_engine_oauth_client_secret if previous else ""
        elif self.send_engine_oauth_client_secret:
            self.send_engine_oauth_client_secret = encrypt_text(self.send_engine_oauth_client_secret)

        super().save(*args, **kwargs)


@register_setting
class SystemNotificationMailSettings(BaseGenericSetting):
    contact_form_from_name = models.CharField(max_length=255, blank=True, verbose_name=_("Contact Form Sender Name"))
    contact_form_from_email = models.EmailField(blank=True, verbose_name=_("Contact Form Sender Email"))
    contact_form_reply_to_email = models.EmailField(blank=True, verbose_name=_("Contact Form Reply-To Email"))
    contact_form_to_emails = models.TextField(
        blank=True,
        help_text=_("Multiple recipients separated by comma or newline."),
        verbose_name=_("Contact Form Notification Recipients"),
    )
    contact_form_subject_prefix = models.CharField(max_length=255, blank=True, default="[Contact Us]", verbose_name=_("Contact Form Subject Prefix"))
    contact_form_user_subject_template = models.CharField(
        max_length=255,
        blank=True,
        default="已收到您的聯絡表單",
        verbose_name=_("User Copy Subject Template"),
    )
    contact_form_user_text_template = models.TextField(
        blank=True,
        default=(
            "您好 {{name}}：\n\n"
            "我們已收到您的來信，以下為存檔資訊：\n"
            "Email: {{email}}\n"
            "聯絡方式: {{contact}}\n"
            "問題類別: {{category}}\n\n"
            "留言內容:\n{{message}}\n"
        ),
        verbose_name=_("User Copy Text Template"),
    )
    contact_form_user_html_template = models.TextField(
        blank=True,
        default=(
            "<p>您好 {{name}}：</p>"
            "<p>我們已收到您的來信，以下為存檔資訊：</p>"
            "<ul>"
            "<li>Email: {{email}}</li>"
            "<li>聯絡方式: {{contact}}</li>"
            "<li>問題類別: {{category}}</li>"
            "</ul>"
            "<p>留言內容：</p>"
            "<p>{{message}}</p>"
        ),
        verbose_name=_("User Copy HTML Template"),
    )
    subscribe_subject_template = models.CharField(
        max_length=255,
        default="請確認您的電子報訂閱",
        verbose_name=_("Subscribe Subject Template"),
    )
    subscribe_html_template = models.TextField(
        default=(
            "<p>您好，請點擊以下連結完成訂閱：</p>"
            "<p><a href='{{confirm_url}}'>{{confirm_url}}</a></p>"
        ),
        verbose_name=_("Subscribe HTML Template"),
    )
    subscribe_text_template = models.TextField(
        default="您好，請點擊以下連結完成訂閱：{{confirm_url}}",
        verbose_name=_("Subscribe Text Template"),
    )
    confirm_success_template = RichTextField(
        blank=True,
        default="<p>訂閱確認成功。</p>",
        verbose_name=_("Confirm Success Template"),
    )
    confirm_failure_template = RichTextField(
        blank=True,
        default="<p>訂閱確認失敗，請稍後再試。</p>",
        verbose_name=_("Confirm Failure Template"),
    )
    unsubscribe_intro_template = RichTextField(
        blank=True,
        default="<p>確認要退訂電子報嗎？</p>",
        verbose_name=_("Unsubscribe Intro Template"),
    )
    unsubscribe_success_template = RichTextField(
        blank=True,
        default="<p>已完成退訂。</p>",
        verbose_name=_("Unsubscribe Success Template"),
    )
    unsubscribe_failure_template = RichTextField(
        blank=True,
        default="<p>退訂失敗，請稍後再試。</p>",
        verbose_name=_("Unsubscribe Failure Template"),
    )
    default_charset = models.CharField(max_length=50, default="utf-8", verbose_name=_("Default Charset"))

    panels = [
        MultiFieldPanel(
            [
                FieldPanel("contact_form_from_name"),
                FieldPanel("contact_form_from_email"),
                FieldPanel("contact_form_reply_to_email"),
                FieldPanel("contact_form_to_emails"),
                FieldPanel("contact_form_subject_prefix"),
                FieldPanel("contact_form_user_subject_template"),
                FieldPanel("contact_form_user_text_template"),
                FieldPanel("contact_form_user_html_template"),
                FieldPanel("default_charset"),
            ],
            heading=_("Contact Us Notification Mail"),
        ),
        MultiFieldPanel(
            [
                FieldPanel("subscribe_subject_template"),
                FieldPanel("subscribe_html_template"),
                FieldPanel("subscribe_text_template"),
            ],
            heading=_("Subscribe Confirmation Email"),
        ),
        MultiFieldPanel(
            [
                FieldPanel("confirm_success_template"),
                FieldPanel("confirm_failure_template"),
                FieldPanel("unsubscribe_intro_template"),
                FieldPanel("unsubscribe_success_template"),
                FieldPanel("unsubscribe_failure_template"),
            ],
            heading=_("Page Templates"),
        ),
    ]

    class Meta:
        verbose_name = _("System Notification Mail Settings")

    def contact_form_recipient_list(self) -> list[str]:
        raw = (self.contact_form_to_emails or "").replace("\n", ",")
        return [item.strip() for item in raw.split(",") if item.strip()]


class OneClickUnsubscribeAudit(models.Model):
    token_hash = models.CharField(max_length=64, unique=True, db_index=True)
    subscriber_id = models.CharField(max_length=128, blank=True)
    list_id = models.CharField(max_length=128, blank=True)
    site_id = models.CharField(max_length=128, blank=True)
    campaign_id = models.CharField(max_length=128, blank=True)
    status = models.CharField(max_length=32, blank=True)
    response_status = models.PositiveIntegerField(null=True, blank=True)
    response_payload = models.JSONField(default=dict, blank=True)
    error_message = models.TextField(blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    processed_at = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ["-created_at"]


class NewsletterCampaign(models.Model):
    TYPE_GENERAL = "general"
    TYPE_WEEKLY_NEWS = "weekly_news"
    TYPE_CHOICES = [
        (TYPE_GENERAL, _("General Newsletter")),
        (TYPE_WEEKLY_NEWS, _("Weekly News Newsletter")),
    ]

    STATUS_DRAFT = "draft"
    STATUS_SCHEDULED = "scheduled"
    STATUS_SENDING = "sending"
    STATUS_SENT = "sent"
    STATUS_FAILED = "failed"
    STATUS_CHOICES = [
        (STATUS_DRAFT, _("Draft")),
        (STATUS_SCHEDULED, _("Scheduled")),
        (STATUS_SENDING, _("Sending")),
        (STATUS_SENT, _("Sent")),
        (STATUS_FAILED, _("Failed")),
    ]

    title = models.CharField(max_length=255, verbose_name=_("Title"))
    campaign_type = models.CharField(
        max_length=32,
        choices=TYPE_CHOICES,
        default=TYPE_GENERAL,
        verbose_name=_("Campaign Type"),
    )
    newsletter_template = models.ForeignKey(
        "base.NewsletterTemplate",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="campaigns",
        verbose_name=_("Newsletter Template"),
    )
    list_id = models.CharField(max_length=128, blank=True, verbose_name=_("List ID"))
    subject_template = models.CharField(max_length=255, verbose_name=_("Subject Template"))
    html_template = RichTextField(verbose_name=_("HTML Template"))
    text_template = models.TextField(blank=True, verbose_name=_("Text Template"))
    weekly_articles = models.ManyToManyField(
        "home.ArticlePage",
        blank=True,
        related_name="newsletter_campaigns",
        verbose_name=_("Weekly Articles"),
    )
    item_template_html = models.TextField(
        blank=True,
        default='''<tr>
  <td height="40" style="height: 40px;">
    &nbsp;
  </td>
</tr>
<tr>
  <td width="100%" style="width:100%">
    <a href="{{article_url}}" target="_blank" rel="newsletter" style="text-decoration: none;">
      <p style="font-weight: 400; font-size: 24px; line-height: 29px; text-align: justify; color: #0E1B42;">
        {{article_title}}
      </p>
    </a>
  </td>
</tr>
<tr>
  <td height="20" style="height: 20px;">
    &nbsp;
  </td>
</tr>
<tr>
  <td>
    <table
      role="presentation"
      width="100%"
      height="333"
      cellspacing="0"
      cellpadding="0"
      border="0"
      style="width:100%; height:333px; border-collapse:collapse; border-spacing:0; margin:0; padding:0;"
    >
      <tbody>
        <tr>
          <td width="96" style="width: 96px; padding:0; margin:0; font-size:0; line-height:0;">&nbsp;</td>
          <td width="596" style="width: 596px; padding:0; margin:0; font-size:0; line-height:0;">
            <a href="{{article_url}}" target="_blank" rel="newsletter">
              <img src="{{article_cover_url}}" alt="{{article_title}}" style="width: 596px; height: 333px;">
            </a>
          </td>
          <td width="96" style="width: 96px; padding:0; margin:0; font-size:0; line-height:0;">&nbsp;</td>
        </tr>
      </tbody>
    </table>
  </td>
</tr>
<tr>
  <td height="40" style="height: 40px;">
    &nbsp;
  </td>
</tr>
<tr>
  <td width="100%" style="width:100%">
    <a href="{{article_url}}" target="_blank" rel="newsletter" style="text-decoration: none;">
      <p style="font-weight: 400; font-size: 20px; line-height: 143%; text-align: justify; color: #0E1B42;">
        {{article_intro}}
      </p>
    </a>
  </td>
</tr>
<tr>
  <td height="40" style="height: 39px; border-bottom: 1pt solid #0E1B42;">
    &nbsp;
  </td>
</tr>''',
        verbose_name=_("Weekly Item HTML Template"),
    )
    content_config = models.JSONField(default=dict, blank=True, verbose_name=_("Content Config"))
    status = models.CharField(max_length=16, choices=STATUS_CHOICES, default=STATUS_DRAFT, verbose_name=_("Status"))
    scheduled_at = models.DateTimeField(null=True, blank=True, verbose_name=_("Scheduled At"))
    sent_at = models.DateTimeField(null=True, blank=True, verbose_name=_("Sent At"))
    last_error = models.TextField(blank=True, verbose_name=_("Last Error"))
    created_at = models.DateTimeField(auto_now_add=True, verbose_name=_("Created At"))
    updated_at = models.DateTimeField(auto_now=True, verbose_name=_("Updated At"))

    panels = [
        FieldPanel("title"),
        FieldPanel("campaign_type"),
        FieldPanel("newsletter_template"),
        FieldPanel("list_id"),
        FieldPanel("subject_template"),
        FieldPanel("html_template"),
        FieldPanel("text_template"),
        FieldPanel("weekly_articles"),
        FieldPanel("item_template_html"),
        FieldPanel("content_config"),
        FieldPanel("scheduled_at"),
    ]

    class Meta:
        ordering = ["-created_at"]
        verbose_name = _("Newsletter Campaign")
        verbose_name_plural = _("Newsletter Campaigns")
        permissions = [
            ("send_newslettercampaign", "Can send newsletter campaign"),
        ]

    def __str__(self):
        return self.title

    def save(self, *args, **kwargs):
        if self._state.adding and not (self.list_id or "").strip():
            default_list_id = (NewsletterSystemSettings.load().member_center_list_id or "").strip()
            if default_list_id:
                self.list_id = default_list_id
        super().save(*args, **kwargs)


class NewsletterTemplate(models.Model):
    name = models.CharField(max_length=255, verbose_name=_("Name"))
    subject = models.CharField(max_length=255, blank=True, default="", verbose_name=_("Subject"))
    template_html = models.TextField(blank=True, default="", verbose_name=_("Template HTML"))
    template_text = models.TextField(blank=True, default="", verbose_name=_("Template Text"))
    created_at = models.DateTimeField(auto_now_add=True, verbose_name=_("Created At"))
    updated_at = models.DateTimeField(auto_now=True, verbose_name=_("Updated At"))

    panels = [
        FieldPanel("name"),
        FieldPanel("subject"),
        FieldPanel("template_html"),
        FieldPanel("template_text"),
    ]

    class Meta:
        ordering = ["-updated_at", "-created_at"]
        verbose_name = _("Newsletter Template")
        verbose_name_plural = _("Newsletter Templates")

    def __str__(self):
        return self.name


class NewsletterDispatchRecord(models.Model):
    campaign = models.ForeignKey(
        NewsletterCampaign,
        on_delete=models.CASCADE,
        related_name="dispatch_records",
        verbose_name=_("Campaign"),
    )
    subscriber_id = models.CharField(max_length=128, blank=True, verbose_name=_("Subscriber ID"))
    email = models.EmailField(blank=True, verbose_name=_("Email"))
    status = models.CharField(max_length=32, blank=True, verbose_name=_("Status"))
    retry_count = models.PositiveIntegerField(default=0, verbose_name=_("Retry Count"))
    next_retry_at = models.DateTimeField(null=True, blank=True, verbose_name=_("Next Retry At"))
    response_status = models.PositiveIntegerField(null=True, blank=True, verbose_name=_("Response Status"))
    response_payload = models.JSONField(default=dict, blank=True, verbose_name=_("Response Payload"))
    error_message = models.TextField(blank=True, verbose_name=_("Error Message"))
    created_at = models.DateTimeField(auto_now_add=True, verbose_name=_("Created At"))

    panels = [
        FieldPanel("campaign"),
        FieldPanel("subscriber_id"),
        FieldPanel("email"),
        FieldPanel("status"),
        FieldPanel("retry_count"),
        FieldPanel("next_retry_at"),
        FieldPanel("response_status"),
        FieldPanel("response_payload"),
        FieldPanel("error_message"),
    ]

    class Meta:
        ordering = ["-created_at"]
        verbose_name = _("Newsletter Dispatch Record")
        verbose_name_plural = _("Newsletter Dispatch Records")

    def __str__(self):
        return f"{self.campaign_id}:{self.email or self.subscriber_id}"


@register_snippet
class BannerSnippet(models.Model):
    key = models.CharField(max_length=50, blank=True, help_text=_("Identifier key, e.g. home / category"), verbose_name=_("Key"))
    title = models.CharField(max_length=255, blank=True, verbose_name=_("Title"))
    image = models.ForeignKey(
        "wagtailimages.Image",
        null=True,
        blank=False,
        on_delete=models.SET_NULL,
        related_name="+",
    )
    link_url = models.URLField(blank=True)
    link_text = models.CharField(max_length=100, blank=True, verbose_name=_("Link Text"))
    is_active = models.BooleanField(default=True, verbose_name=_("Active"))
    sort_order = models.PositiveIntegerField(default=0, verbose_name=_("Sort Order"))

    panels = [
        FieldPanel("key"),
        FieldPanel("title"),
        FieldPanel("image"),
        FieldPanel("link_url"),
        FieldPanel("link_text"),
        FieldPanel("is_active"),
        FieldPanel("sort_order"),
    ]

    class Meta:
        ordering = ["sort_order", "id"]
        verbose_name = _("Banner")
        verbose_name_plural = _("Banners")

    def __str__(self):
        return self.title or f"Banner {self.pk}"

@register_snippet
class FooterText(
    DraftStateMixin,
    RevisionMixin,
    PreviewableMixin,
    TranslatableMixin,
    models.Model,
):

    body = RichTextField()

    panels = [
        FieldPanel("body"),
        PublishingPanel(),
    ]

    def __str__(self):
        return "Footer text"

    def get_preview_template(self, request, mode_name):
        return "base.html"

    def get_preview_context(self, request, mode_name):
        return {"footer_text": self.body}

    class Meta(TranslatableMixin.Meta):
        verbose_name_plural = _("Footer Text")


class ContactFormSubmission(models.Model):
    CATEGORY_COLLABORATION = "collaboration"
    CATEGORY_WEBSITE_ISSUE = "website_issue"
    CATEGORY_CAREER = "career"
    CATEGORY_OTHER = "other"
    CATEGORY_CHOICES = [
        (CATEGORY_COLLABORATION, _("Collaboration")),
        (CATEGORY_WEBSITE_ISSUE, _("Website Issue")),
        (CATEGORY_CAREER, _("Career")),
        (CATEGORY_OTHER, _("Other")),
    ]

    STATUS_QUEUED = "queued"
    STATUS_SCANNING = "scanning"
    STATUS_SCAN_RETRY = "scan_retry"
    STATUS_BLOCKED = "blocked"
    STATUS_SENDING = "sending"
    STATUS_SEND_RETRY = "send_retry"
    STATUS_SENT = "sent"
    STATUS_FAILED = "failed"
    STATUS_RATE_LIMITED = "rate_limited"
    STATUS_LEGACY = "legacy"
    STATUS_CHOICES = [
        (STATUS_QUEUED, _("Queued")),
        (STATUS_SCANNING, _("Scanning")),
        (STATUS_SCAN_RETRY, _("Scan Retry")),
        (STATUS_BLOCKED, _("Blocked as Spam")),
        (STATUS_SENDING, _("Sending")),
        (STATUS_SEND_RETRY, _("Send Retry")),
        (STATUS_SENT, _("Sent")),
        (STATUS_FAILED, _("Failed")),
        (STATUS_RATE_LIMITED, _("Rate Limited")),
        (STATUS_LEGACY, _("Legacy Submission")),
    ]

    SPAM_CATEGORY_CHOICES = [
        (0, _("Allowed")),
        (1, _("Unsolicited Advertising")),
        (2, _("Malicious")),
        (3, _("Meaningless")),
    ]

    name = models.CharField(max_length=100, verbose_name=_("Name"))
    email = models.EmailField(blank=True, verbose_name=_("Email"))
    contact = models.CharField(max_length=255, verbose_name=_("Contact"))
    category = models.CharField(max_length=32, choices=CATEGORY_CHOICES, verbose_name=_("Category"))
    message = models.TextField(verbose_name=_("Message"))
    source_page = models.CharField(max_length=512, blank=True, verbose_name=_("Source Page"))
    ip_address = models.GenericIPAddressField(null=True, blank=True, verbose_name=_("IP Address"))
    user_agent = models.TextField(blank=True, verbose_name=_("User Agent"))
    processing_status = models.CharField(
        max_length=20,
        choices=STATUS_CHOICES,
        default=STATUS_QUEUED,
        db_index=True,
        verbose_name=_("Processing Status"),
    )
    spam_category = models.PositiveSmallIntegerField(
        choices=SPAM_CATEGORY_CHOICES,
        null=True,
        blank=True,
        verbose_name=_("Spam Category"),
    )
    spam_source = models.CharField(max_length=32, blank=True, verbose_name=_("Spam Detection Source"))
    spam_checked_at = models.DateTimeField(null=True, blank=True, verbose_name=_("Spam Checked At"))
    scan_attempt_count = models.PositiveIntegerField(default=0, verbose_name=_("Scan Attempt Count"))
    send_attempt_count = models.PositiveIntegerField(default=0, verbose_name=_("Send Attempt Count"))
    next_attempt_at = models.DateTimeField(null=True, blank=True, db_index=True, verbose_name=_("Next Attempt At"))
    processing_started_at = models.DateTimeField(null=True, blank=True, verbose_name=_("Processing Started At"))
    notification_sent_at = models.DateTimeField(null=True, blank=True, verbose_name=_("Notification Sent At"))
    user_copy_sent_at = models.DateTimeField(null=True, blank=True, verbose_name=_("User Copy Sent At"))
    last_error = models.TextField(blank=True, verbose_name=_("Last Error"))
    created_at = models.DateTimeField(auto_now_add=True, verbose_name=_("Created At"))
    updated_at = models.DateTimeField(auto_now=True, verbose_name=_("Updated At"))

    class Meta:
        ordering = ["-created_at"]
        indexes = [
            models.Index(fields=["ip_address", "created_at"], name="contact_ip_created_idx"),
            models.Index(
                fields=["processing_status", "next_attempt_at", "created_at"],
                name="contact_process_due_idx",
            ),
        ]
        verbose_name = _("Contact Form Submission")
        verbose_name_plural = _("Contact Form Submissions")

    def __str__(self):
        return f"{self.get_category_display()} - {self.name}"


class ContactFormRateLimitBucket(models.Model):
    ip_address = models.GenericIPAddressField(unique=True, verbose_name=_("IP Address"))
    updated_at = models.DateTimeField(auto_now=True, verbose_name=_("Updated At"))

    class Meta:
        verbose_name = _("Contact Form Rate Limit Bucket")
        verbose_name_plural = _("Contact Form Rate Limit Buckets")


class ContactSpamDetectionState(models.Model):
    lock_token = models.CharField(max_length=64, blank=True, verbose_name=_("Lock Token"))
    locked_until = models.DateTimeField(null=True, blank=True, verbose_name=_("Locked Until"))
    cooldown_until = models.DateTimeField(null=True, blank=True, verbose_name=_("Cooldown Until"))
    last_error = models.TextField(blank=True, verbose_name=_("Last Error"))
    updated_at = models.DateTimeField(auto_now=True, verbose_name=_("Updated At"))

    class Meta:
        verbose_name = _("Contact Spam Detection State")
        verbose_name_plural = _("Contact Spam Detection State")
