from django.conf import settings
from django.db import models
from django.utils import timezone
from ckeditor.fields import RichTextField

from . import fonts

class SiteSettings(models.Model):
    site_name           = models.CharField(max_length=100, default="The Reverse Times")
    tagline             = models.CharField(max_length=255)
    logo                = models.ImageField(upload_to='site/', blank=True)
    favicon             = models.ImageField(upload_to='site/', blank=True)
    about_text          = RichTextField()
    footer_text         = models.TextField()
    contact_email       = models.EmailField()
    social_twitter      = models.URLField(blank=True, verbose_name="X (Twitter)")
    social_facebook     = models.URLField(blank=True, verbose_name="Facebook")
    social_instagram    = models.URLField(blank=True, verbose_name="Instagram")
    social_youtube      = models.URLField(blank=True, verbose_name="YouTube")
    social_linkedin     = models.URLField(blank=True, verbose_name="LinkedIn")
    social_tiktok       = models.URLField(blank=True, verbose_name="TikTok")
    social_threads      = models.URLField(blank=True, verbose_name="Threads")
    social_reddit       = models.URLField(blank=True, verbose_name="Reddit")
    social_whatsapp     = models.URLField(blank=True, verbose_name="WhatsApp Channel")
    homepage_hero_count = models.PositiveSmallIntegerField(default=1)
    homepage_featured_count = models.PositiveSmallIntegerField(default=6)
    meta_description    = models.TextField(blank=True)
    meta_keywords       = models.TextField(blank=True)
    google_analytics_id = models.CharField(max_length=50, blank=True)
    # Fonts (each slot can be changed independently)
    font_en_heading = models.CharField("English headings", max_length=40, default='Playfair Display', choices=fonts.choices(fonts.EN_HEADING))
    font_en_body = models.CharField("English body text", max_length=40, default='Crimson Pro', choices=fonts.choices(fonts.EN_BODY))
    font_en_accent = models.CharField("English accent (italic)", max_length=40, default='Cormorant Garamond', choices=fonts.choices(fonts.EN_ACCENT))
    font_en_label = models.CharField("English labels & buttons", max_length=40, default='Bebas Neue', choices=fonts.choices(fonts.EN_LABEL))
    font_bn_heading = models.CharField("Bangla headings", max_length=40, default='Noto Serif Bengali', choices=fonts.choices(fonts.BN_HEADING))
    font_bn_body = models.CharField("Bangla body text", max_length=40, default='Noto Serif Bengali', choices=fonts.choices(fonts.BN_BODY))
    font_bn_ui = models.CharField("Bangla labels, buttons & numbers", max_length=40, default='Noto Sans Bengali', choices=fonts.choices(fonts.BN_UI),
                                  help_text="Used for small Bangla text and Bangla digits (১২৩). Pick a font with clear numbers.")
    google_site_verification = models.CharField(
        max_length=120, blank=True,
        help_text="Google Search Console → Add property → HTML tag method. Paste only the content value.")
    bing_site_verification = models.CharField(
        max_length=120, blank=True,
        help_text="Bing Webmaster Tools 'msvalidate.01' value. Bing also powers ChatGPT search and Copilot.")
    maintenance_mode    = models.BooleanField(default=False)

    HERO_LAYOUT_CHOICES = (
        ('split', 'Split (Image one side, text another)'),
        ('top_image', 'Top Image (Full width, half height)'),
        ('overlay', 'Overlay (Full section image, text overlay)'),
        ('grid3', '3-Column Grid (1 Large, 2 Small)'),
    )
    hero_layout = models.CharField(max_length=20, choices=HERO_LAYOUT_CHOICES, default='split')
    hero_autoplay_seconds = models.PositiveSmallIntegerField(
        "Hero slider: seconds per slide", default=7,
        help_text="How long each homepage hero slide stays before moving on. 0 = don't move on its own.")

    class Meta:
        verbose_name = "Site Settings"
        verbose_name_plural = "Site Settings"

    @classmethod
    def get_solo(cls):
        obj, created = cls.objects.get_or_create(id=1)
        return obj

    def __str__(self):
        return self.site_name

class StaticPage(models.Model):
    title       = models.CharField(max_length=200)
    slug        = models.SlugField(unique=True)
    content     = RichTextField()
    is_published = models.BooleanField(default=True)
    show_in_footer = models.BooleanField(default=False)
    meta_description = models.TextField(blank=True)
    created_at  = models.DateTimeField(auto_now_add=True)
    updated_at  = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.title


class ContactMessage(models.Model):
    PURPOSE_CHOICES = (
        ('submit_article', 'Submit an Article / Writing'),
        ('feedback', 'Feedback / Suggestion'),
        ('correction', 'Report a Correction'),
        ('collaboration', 'Collaboration / Partnership'),
        ('advertising', 'Advertising Inquiry'),
        ('press', 'Press / Media Inquiry'),
        ('general', 'General Inquiry'),
        ('other', 'Other'),
    )
    STATUS_CHOICES = (
        ('new', 'New'),
        ('read', 'Read'),
        ('replied', 'Replied'),
        ('archived', 'Archived'),
    )

    name        = models.CharField(max_length=200)
    email       = models.EmailField()
    purpose     = models.CharField(max_length=30, choices=PURPOSE_CHOICES, default='general')
    message     = models.TextField()
    attachment  = models.FileField(upload_to='contact_attachments/%Y/%m/', blank=True, null=True,
                                   help_text="Optional file attachment (PDF, DOC, images, etc.)")
    status      = models.CharField(max_length=15, choices=STATUS_CHOICES, default='new')
    admin_notes = models.TextField(blank=True, help_text="Internal notes (not visible to sender)")
    created_at  = models.DateTimeField(auto_now_add=True)

    class Meta:
        verbose_name = "Contact Message"
        verbose_name_plural = "Contact Messages"
        ordering = ['-created_at']

    def __str__(self):
        return f"[{self.get_purpose_display()}] {self.name} — {self.email}"


# ─── Admin-Configurable Page Content ───────────────────────────────────────────

class SingletonMixin:
    """Mixin that ensures only one row exists (singleton pattern)."""
    @classmethod
    def get_solo(cls):
        obj, _ = cls.objects.get_or_create(id=1)
        return obj


class AboutPageContent(SingletonMixin, models.Model):
    # Hero section
    hero_badge      = models.CharField(max_length=100, default="Est. 2023 · Bangladesh")
    hero_title      = models.CharField(max_length=200, default="About <em>The Reverse Times</em>",
                                       help_text="Use &lt;em&gt; tags for italic/gold text")
    hero_tagline    = models.TextField(default="Bangladesh's first historical magazine — dedicated to uncovering the stories, places, people, and naming histories that shaped our nation and the world.")

    # Our Story section
    our_story       = RichTextField(default="", blank=True, help_text="Rich text for the 'Our Story' section")

    # Mission section
    mission_quote   = models.TextField(default="", blank=True,
                                       help_text="The big italic mission quote")
    mission_body    = models.TextField(default="", blank=True,
                                       help_text="Body text below the mission quote")

    # CTA section
    cta_title       = models.CharField(max_length=200, default="Start Exploring <em>History</em>",
                                       help_text="Use &lt;em&gt; for italic/gold text")
    cta_subtitle    = models.TextField(default="Dive into deeply researched articles on Bangladesh history, naming history, ancient civilizations, and cultural heritage.")

    class Meta:
        verbose_name = "About Page"
        verbose_name_plural = "About Page"

    def __str__(self):
        return "About Page Content"


class ContactPageContent(SingletonMixin, models.Model):
    # Hero section
    hero_badge      = models.CharField(max_length=100, default="Get in Touch")
    hero_title      = models.CharField(max_length=200, default="Contact <em>Us</em>",
                                       help_text="Use &lt;em&gt; tags for italic/gold text")
    hero_tagline    = models.TextField(default="Have a story to share, a correction to suggest, or simply want to say hello? We'd love to hear from you.")

    # Info panel
    info_title      = models.CharField(max_length=200, default="Reach Out to <em>Our Editorial Team</em>",
                                       help_text="Left panel title")
    info_description = models.TextField(default="Whether you're a historian, researcher, student, or simply passionate about history — we welcome your correspondence.")

    # Contact details
    email_address   = models.EmailField(default="editor@thereversetimes.com")
    response_time   = models.CharField(max_length=100, default="We respond within 48 hours")

    class Meta:
        verbose_name = "Contact Page"
        verbose_name_plural = "Contact Page"

    def __str__(self):
        return "Contact Page Content"


class SubmitPageContent(SingletonMixin, models.Model):
    # Hero section
    hero_badge      = models.CharField(max_length=100, default="Letters to the Editor")
    hero_title      = models.CharField(max_length=200, default="Submit Your <em>Writing</em>",
                                       help_text="Use &lt;em&gt; tags for italic/gold text")
    hero_tagline    = models.TextField(default="Share your historical research, findings, and perspectives with The Reverse Times. Every voice that speaks for history deserves to be heard.")

    # Guidelines panel
    guidelines_title = models.CharField(max_length=200, default="Submission <em>Guidelines</em>",
                                        help_text="Left panel heading")
    guidelines_description = models.TextField(default="We welcome original research, essays, photo essays, and documentary projects on any aspect of history — especially Bangladesh history, naming history, and cultural heritage.")

    class Meta:
        verbose_name = "Submit Article Page"
        verbose_name_plural = "Submit Article Page"

    def __str__(self):
        return "Submit Page Content"


class TeamPageContent(SingletonMixin, models.Model):
    # Hero section
    hero_badge      = models.CharField(max_length=100, default="The People Behind The Pages")
    hero_title      = models.CharField(max_length=200, default="Our <em>Team</em>",
                                       help_text="Use &lt;em&gt; tags for italic/gold text")
    hero_tagline    = models.TextField(default="Meet the historians, researchers, and writers who bring Bangladesh's rich history to life — one article at a time.")

    # Editorial Board section
    board_label     = models.CharField(max_length=100, default="Leadership")
    board_title     = models.CharField(max_length=200, default="Editorial <em>Board</em>")
    board_description = models.TextField(default="The editorial board guides every issue of The Reverse Times — ensuring historical accuracy, scholarly rigor, and compelling storytelling.")

    # Contributors section
    contrib_label   = models.CharField(max_length=100, default="Writers & Researchers")
    contrib_title   = models.CharField(max_length=200, default="Our <em>Contributors</em>")
    contrib_description = models.TextField(default="Historians, academics, photojournalists, and filmmakers who contribute their expertise to our pages.")

    # CTA section
    cta_title       = models.CharField(max_length=200, default="Join Our <em>Team</em>")
    cta_description = models.TextField(default="We are always looking for passionate historians, researchers, and storytellers. If you have a story to tell about Bangladesh's rich past, we'd love to hear from you.")

    class Meta:
        verbose_name = "Team Page"
        verbose_name_plural = "Team Page"

    def __str__(self):
        return "Team Page Content"


class EditorialBoardMember(models.Model):
    name    = models.CharField(max_length=200)
    role    = models.CharField(max_length=200, help_text="e.g. Editor-in-Chief, Managing Editor")
    bio     = models.TextField(help_text="Short biography")
    photo   = models.ImageField(upload_to='team/editorial/', blank=True, null=True,
                                help_text="Square photo recommended (min 200×200)")
    order   = models.PositiveSmallIntegerField(default=0, help_text="Display order (lower = first)")
    is_active = models.BooleanField(default=True)

    class Meta:
        verbose_name = "Editorial Board Member"
        verbose_name_plural = "Editorial Board Members"
        ordering = ['order', 'name']

    def __str__(self):
        return f"{self.name} — {self.role}"


class Contributor(models.Model):
    name      = models.CharField(max_length=200)
    role      = models.CharField(max_length=200, help_text="e.g. Contributing Writer, Photojournalist")
    specialty = models.CharField(max_length=200, help_text="e.g. Mughal Architecture, Liberation War 1971")
    photo     = models.ImageField(upload_to='team/contributors/', blank=True, null=True,
                                  help_text="Square photo recommended (min 200×200)")
    order     = models.PositiveSmallIntegerField(default=0, help_text="Display order (lower = first)")
    is_active = models.BooleanField(default=True)

    class Meta:
        verbose_name = "Contributor"
        verbose_name_plural = "Contributors"
        ordering = ['order', 'name']

    def __str__(self):
        return f"{self.name} — {self.role}"


class YouTubeVideo(models.Model):
    """Featured YouTube videos from The Reverse Times channel."""
    embed_url   = models.TextField(
        help_text="Paste the YouTube video URL, embed URL, or the full iframe embed code."
    )
    title       = models.CharField(max_length=300)
    description = models.TextField(blank=True, help_text="Short description for the video card")
    order       = models.PositiveSmallIntegerField(default=0, help_text="Display order (lower = first)")
    is_active   = models.BooleanField(default=True)
    created_at  = models.DateTimeField(auto_now_add=True)

    class Meta:
        verbose_name = "YouTube Video"
        verbose_name_plural = "YouTube Videos"
        ordering = ['order', '-created_at']

    def __str__(self):
        return self.title

    @property
    def video_id(self):
        """Extract the video ID from the embed code or URL."""
        import re
        text = self.embed_url
        
        # If it's an iframe, extract the src attribute
        src_match = re.search(r'src="([^"]+)"', text)
        if src_match:
            text = src_match.group(1)
            
        # e.g. https://www.youtube.com/embed/dQw4w9WgXcQ
        if '/embed/' in text:
            return text.split('/embed/')[-1].split('?')[0].strip('"/\\')
        # e.g. https://www.youtube.com/watch?v=dQw4w9WgXcQ
        elif 'v=' in text:
            return text.split('v=')[-1].split('&')[0].strip('"/\\')
        # e.g. https://youtu.be/dQw4w9WgXcQ
        elif 'youtu.be/' in text:
            return text.split('youtu.be/')[-1].split('?')[0].strip('"/\\')
        
        # Fallback (maybe they just pasted the ID)
        return text.strip()

    @property
    def thumbnail_url(self):
        vid = self.video_id
        if vid:
            return f"https://img.youtube.com/vi/{vid}/hqdefault.jpg"
        return ''


# ─── Editable Site-Wide Content ────────────────────────────────────────────────

class HomepageContent(SingletonMixin, models.Model):
    """Editable text for the homepage (article_list.html)."""
    # Nav bar
    volume_label        = models.CharField(max_length=50, default="Vol. I",
                                           help_text="Magazine volume shown in top-left nav, e.g. 'Vol. I'")
    # Hero section
    hero_cta_text       = models.CharField(max_length=100, default="Read Feature",
                                           help_text="Hero button text")
    # Section headings
    featured_label      = models.CharField(max_length=100, default="Featured Articles")
    editorial_label     = models.CharField(max_length=100, default="Opinion & Analysis")
    archives_label      = models.CharField(max_length=100, default="From the Archives")
    recent_label        = models.CharField(max_length=100, default="Recent Dispatches")
    youtube_label       = models.CharField(max_length=100, default="From Our Channel",
                                           help_text="YouTube section heading")
    timeline_label      = models.CharField(max_length=100, default="Historical Timeline")

    class Meta:
        verbose_name = "Homepage Content"
        verbose_name_plural = "Homepage Content"

    def __str__(self):
        return "Homepage Content"


class HomepageSection(models.Model):
    """Admin-configurable category sections on the homepage."""
    category        = models.ForeignKey('articles.Category', on_delete=models.CASCADE,
                                        related_name='homepage_sections')
    heading_override = models.CharField(max_length=200, blank=True,
                                        help_text="Custom heading (leave blank to use category name)")
    max_articles    = models.PositiveSmallIntegerField(default=6,
                                                       help_text="Max articles to display in this section")
    show_view_all   = models.BooleanField(default=True,
                                          help_text="Show 'View All' button if category has more articles")
    order           = models.PositiveSmallIntegerField(default=0,
                                                       help_text="Display order (lower = higher on page)")
    is_active       = models.BooleanField(default=True)

    class Meta:
        verbose_name = "Homepage Section"
        verbose_name_plural = "Homepage Sections"
        ordering = ['order']

    def __str__(self):
        return self.heading_override or self.category.name

    @property
    def display_heading(self):
        return self.heading_override or self.category.name


class SubscribeContent(SingletonMixin, models.Model):
    """Editable text for the subscribe/newsletter section."""
    heading         = models.CharField(max_length=300, default="History, <em>Delivered<br>Monthly</em>",
                                       help_text="Use &lt;em&gt; for italic/accent text, &lt;br&gt; for line break")
    description     = models.TextField(default="Join 240,000 readers who receive deeply researched essays, archival discoveries, and long-form narratives about the past that illuminate the present.")
    button_text     = models.CharField(max_length=100, default="Subscribe to The Reverse Times")
    name_placeholder = models.CharField(max_length=100, default="Your full name")
    email_placeholder = models.CharField(max_length=100, default="Your email address")

    class Meta:
        verbose_name = "Subscribe Section"
        verbose_name_plural = "Subscribe Section"

    def __str__(self):
        return "Subscribe Section Content"


class FooterContent(SingletonMixin, models.Model):
    """Editable footer text and links."""
    brand_name      = models.CharField(max_length=100, default="The Reverse Times")
    brand_description = models.TextField(default="Bangladesh's first historical magazine dedicated to the history of Bangladesh, naming history of places and people, ancient Bengal, Mughal Bengal, Bengal Sultanate, Bangladesh archaeology, and cultural heritage. Published monthly since 2023. Independent. Rigorous. Unforgettable.")
    copyright_text  = models.CharField(max_length=300, default="© 2026 The Reverse Times · Est. 2023 · All Rights Reserved")

    # Footer link URLs
    privacy_url     = models.CharField(max_length=300, default="#", help_text="Privacy policy page URL or slug")
    terms_url       = models.CharField(max_length=300, default="#", help_text="Terms of service page URL or slug")
    cookie_url      = models.CharField(max_length=300, default="#", help_text="Cookie policy page URL or slug")

    # Column headings
    sections_heading = models.CharField(max_length=50, default="Sections")
    about_heading    = models.CharField(max_length=50, default="About")
    archives_heading = models.CharField(max_length=50, default="Archives")

    class Meta:
        verbose_name = "Footer Content"
        verbose_name_plural = "Footer Content"

    def __str__(self):
        return "Footer Content"


class NavContent(SingletonMixin, models.Model):
    """Editable navigation bar text."""
    search_placeholder = models.CharField(max_length=200, default="Search articles, eras, authors...")
    more_label         = models.CharField(max_length=50, default="More")
    # "More" dropdown links text
    archives_text      = models.CharField(max_length=50, default="Archives")
    subscribe_text     = models.CharField(max_length=50, default="Subscribe")
    editorial_text     = models.CharField(max_length=50, default="Editorial")
    about_text         = models.CharField(max_length=50, default="About Us")
    submit_text        = models.CharField(max_length=50, default="Submit Article")
    contact_text       = models.CharField(max_length=50, default="Contact")

    class Meta:
        verbose_name = "Navigation Content"
        verbose_name_plural = "Navigation Content"

    def __str__(self):
        return "Navigation Content"


# ─── Analytics ────────────────────────────────────────────────────────────────

class VisitorLog(models.Model):
    """One page view by a real person.

    Rows are written by a small script in the browser only after the visitor scrolls, taps,
    clicks or types, so search bots, link previews and uptime checkers are not counted.
    Time spent is the time the tab was actually visible (capped at 30 minutes per page)."""
    DEVICES = (('mobile', 'Mobile'), ('tablet', 'Tablet'), ('desktop', 'Desktop'))

    view_id = models.CharField(max_length=32, unique=True, null=True, blank=True, editable=False)
    visitor_id = models.CharField("Visitor", max_length=32, blank=True, db_index=True,
                                  help_text="Anonymous ID kept in the visitor's browser")
    user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True, on_delete=models.SET_NULL,
                             related_name='page_views')
    is_human = models.BooleanField("Real visitor", default=False, db_index=True,
                                   help_text="False for old rows logged before bot filtering")
    ip_address = models.GenericIPAddressField(null=True, blank=True)
    session_key = models.CharField(max_length=40, null=True, blank=True)
    page_visited = models.CharField(max_length=255)
    referrer = models.CharField(max_length=255, blank=True)
    device = models.CharField(max_length=10, choices=DEVICES, blank=True)
    visit_time = models.DateTimeField(default=timezone.now, db_index=True)
    last_seen = models.DateTimeField(null=True, blank=True)
    time_spent_seconds = models.PositiveIntegerField(default=0)
    page_title = models.CharField(max_length=200, blank=True)
    scroll_pct = models.PositiveSmallIntegerField("Scrolled (%)", default=0,
                                                  help_text="How far down the page the reader got")
    utm_source = models.CharField("Campaign source", max_length=60, blank=True)
    utm_medium = models.CharField("Campaign medium", max_length=60, blank=True)
    utm_campaign = models.CharField("Campaign", max_length=100, blank=True)

    class Meta:
        verbose_name = "Visitor Log"
        verbose_name_plural = "Visitor Logs"
        ordering = ['-visit_time']

    def __str__(self):
        return f"{self.page_visited} at {self.visit_time:%Y-%m-%d %H:%M}"


class ClickEvent(models.Model):
    """One click by a real visitor: what they clicked and where on the page.

    x/y are stored in tenths of a percent of the full page width/height, so clicks
    can be drawn over the page as a click map whatever the page length."""
    KINDS = (('link', 'Link'), ('button', 'Button'), ('outbound', 'Link to another site'), ('other', 'Not a link'))

    view = models.ForeignKey(VisitorLog, on_delete=models.CASCADE, related_name='clicks')
    page = models.CharField(max_length=255, db_index=True)
    label = models.CharField(max_length=120, blank=True)
    href = models.CharField(max_length=300, blank=True)
    kind = models.CharField(max_length=10, choices=KINDS, default='link')
    section = models.CharField(max_length=60, blank=True, help_text="The page section the click was in")
    x = models.PositiveSmallIntegerField(default=0)
    y = models.PositiveSmallIntegerField(default=0)
    created_at = models.DateTimeField(default=timezone.now, db_index=True)

    class Meta:
        ordering = ['-created_at']

    def __str__(self):
        return f"{self.label or self.href or self.kind} on {self.page}"

# ─── Popup Modal ───────────────────────────────────────────────────────────────

class PopupModal(models.Model):
    title = models.CharField(max_length=200)
    subtitle = models.TextField(blank=True, help_text="Optional subtitle or description")
    image = models.ImageField(upload_to='modals/', blank=True, null=True, help_text="Optional image")
    button_text = models.CharField(max_length=50, default="Shop Now")
    button_url = models.CharField(max_length=500, default="/shop/")
    delay_seconds = models.PositiveIntegerField(default=10, help_text="Time in seconds before the modal appears")
    is_active = models.BooleanField(default=True, help_text="If multiple are active, the latest one is shown")
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        verbose_name = "Popup Modal"
        verbose_name_plural = "Popup Modals"
        ordering = ['-created_at']

    def __str__(self):
        return f"{self.title} ({'Active' if self.is_active else 'Inactive'})"




# ─── Homepage blocks (sections you build in the admin) ─────────────────────────

class HomepageBlock(models.Model):
    KIND_CHOICES = (
        ('magazines', 'Magazine issues (latest)'),
        ('merch', 'Wearable History products (latest)'),
        ('nostalgic', 'Nostalgic items (latest)'),
        ('products', 'Hand-picked products'),
        ('articles', 'Hand-picked articles'),
        ('category', 'Latest articles from a category'),
        ('games', 'History games'),
        ('text', 'Custom text / announcement'),
    )
    THEME_CHOICES = (('default', 'Same as page'), ('paper', 'Paper (light)'), ('dark', 'Dark band'))

    kind = models.CharField(max_length=12, choices=KIND_CHOICES, default='products')
    eyebrow = models.CharField(max_length=80, blank=True, help_text="Small label above the title, e.g. 'নতুন সংখ্যা'.")
    title = models.CharField(max_length=150)
    subtitle = models.CharField(max_length=300, blank=True)
    products = models.ManyToManyField('store.Product', blank=True, related_name='homepage_blocks',
                                      help_text="Only for 'Hand-picked products'.")
    articles = models.ManyToManyField('articles.Article', blank=True, related_name='homepage_blocks',
                                      help_text="Only for 'Hand-picked articles'.")
    category = models.ForeignKey('articles.Category', null=True, blank=True, on_delete=models.SET_NULL,
                                 help_text="Only for 'Latest articles from a category'.")
    body = RichTextField(blank=True, help_text="Only for 'Custom text'.")
    image = models.ImageField(upload_to='homepage/', blank=True, help_text="Optional image (Custom text).")
    max_items = models.PositiveSmallIntegerField(default=4, help_text="How many cards to show.")
    see_all_text = models.CharField(max_length=60, blank=True, default='See all',
                                    help_text="Button text. Leave blank to hide the button.")
    see_all_url = models.CharField(max_length=300, blank=True,
                                   help_text="Where the button goes. Blank = the matching page automatically.")
    theme = models.CharField(max_length=8, choices=THEME_CHOICES, default='default')
    order = models.PositiveSmallIntegerField(default=0, help_text="Lower numbers appear first.")
    is_active = models.BooleanField(default=True)

    class Meta:
        ordering = ['order', 'id']
        verbose_name = "Homepage block"
        verbose_name_plural = "Homepage blocks (sections)"

    def __str__(self):
        return f"{self.title} ({self.get_kind_display()})"

    def items(self):
        from apps.articles.models import Article
        from apps.store.models import Product
        n = self.max_items or 4
        live = Product.objects.filter(is_active=True)
        if self.kind in ('magazines', 'merch', 'nostalgic'):
            ptype = {'magazines': 'magazine'}.get(self.kind, self.kind)
            return list(live.filter(product_type=ptype).order_by('-is_featured', '-published_on', '-created_at')[:n])
        if self.kind == 'products':
            return list(self.products.filter(is_active=True)[:n])
        if self.kind == 'games':
            from apps.games.models import Game
            return list(Game.objects.filter(is_active=True)[:n])
        if self.kind == 'articles':
            return list(self.articles.filter(status='published').select_related('author')[:n])
        if self.kind == 'category' and self.category_id:
            return list(Article.objects.filter(status='published', categories=self.category)
                        .select_related('author').order_by('-published_at')[:n])
        return []

    @property
    def is_article_block(self):
        return self.kind in ('articles', 'category')

    @property
    def link(self):
        if self.see_all_url:
            return self.see_all_url
        from django.urls import reverse
        return {
            'magazines': reverse('magazine'),
            'merch': reverse('shop_merch'),
            'nostalgic': reverse('shop_nostalgic'),
            'products': reverse('shop'),
            'games': reverse('games'),
            'articles': reverse('article_list'),
            'category': reverse('category_detail', args=[self.category.slug]) if self.category_id else '',
        }.get(self.kind, '')


# ─── Homepage hero slider ──────────────────────────────────────────────────────

class HeroSlide(models.Model):
    """One slide in the homepage hero. When at least one slide is active, the hero becomes a slider;
    with none, the homepage shows the featured article as before."""
    KINDS = (
        ('article', 'Blog article'),
        ('magazine', 'Magazine issue'),
        ('product', 'Shop product'),
        ('custom', 'Custom (your own image, text and link)'),
    )
    POSITIONS = (('center', 'Center'), ('top', 'Top'), ('bottom', 'Bottom'), ('left', 'Left'), ('right', 'Right'))

    kind = models.CharField(max_length=10, choices=KINDS, default='article')
    article = models.ForeignKey('articles.Article', null=True, blank=True, on_delete=models.CASCADE,
                                related_name='hero_slides', help_text="For 'Blog article'.")
    product = models.ForeignKey('store.Product', null=True, blank=True, on_delete=models.CASCADE,
                                related_name='hero_slides', help_text="For 'Magazine issue' or 'Shop product'.")
    eyebrow = models.CharField(max_length=80, blank=True, help_text="Small line above the title. Blank = automatic.")
    title = models.CharField(max_length=200, blank=True, help_text="Blank = the article/issue/product title.")
    text = models.TextField(blank=True, max_length=400, help_text="Short text under the title. Blank = automatic.")
    button_text = models.CharField(max_length=60, blank=True, help_text="Blank = automatic (e.g. 'Read feature').")
    button_url = models.CharField(max_length=300, blank=True, help_text="Blank = the article/issue/product page.")
    image = models.ImageField(upload_to='homepage/slides/', blank=True,
                              help_text="Wide background picture (about 1920×1000). Blank = the article's picture, "
                                        "or a soft blur of the cover/product photo.")
    PHONE_DISPLAY = (('custom', 'Phone background picture below (no picture if empty)'),
                     ('product', 'The cover / product photo'))
    phone_display = models.CharField("On phones, show", max_length=8, choices=PHONE_DISPLAY, default='custom',
                                     help_text="Magazine and product slides only: what the slide shows on phones and small tablets.")
    phone_image = models.ImageField("Phone background picture", upload_to='homepage/slides/', blank=True,
                                    help_text="Tall picture for phones (about 1080×1350). Empty = the wide picture above; "
                                              "for magazine/product slides set to the option above, empty means no picture.")
    image_position = models.CharField("Focus of the picture", max_length=8, choices=POSITIONS, default='center',
                                      help_text="Which part of the picture stays visible on narrow phone screens.")
    order = models.PositiveSmallIntegerField(default=0, help_text="Lower numbers come first.")
    is_active = models.BooleanField(default=True)
    starts_at = models.DateTimeField(null=True, blank=True, help_text="Optional: show from this time.")
    ends_at = models.DateTimeField(null=True, blank=True, help_text="Optional: stop showing after this time.")

    class Meta:
        ordering = ['order', 'id']
        verbose_name = "Homepage hero slide"
        verbose_name_plural = "Homepage hero slides"

    def __str__(self):
        return f"{self.get_kind_display()}: {self.title or self.source or '—'}"

    @property
    def source(self):
        return self.article if self.kind == 'article' else self.product if self.kind in ('magazine', 'product') else None

    def clean(self):
        from django.core.exceptions import ValidationError
        if self.kind == 'article' and not self.article_id:
            raise ValidationError({'article': 'Choose the article for this slide.'})
        if self.kind in ('magazine', 'product') and not self.product_id:
            raise ValidationError({'product': 'Choose the magazine issue or product for this slide.'})
        if self.kind == 'magazine' and self.product_id and self.product.product_type != 'magazine':
            raise ValidationError({'product': 'This product is not a magazine issue — use “Shop product”.'})
        if self.kind == 'custom' and not (self.title and self.image):
            raise ValidationError('A custom slide needs at least a title and a picture.')

    @classmethod
    def live(cls):
        from django.db.models import Q
        from django.utils import timezone
        now = timezone.now()
        qs = (cls.objects.filter(is_active=True)
              .filter(Q(starts_at__isnull=True) | Q(starts_at__lte=now))
              .filter(Q(ends_at__isnull=True) | Q(ends_at__gte=now))
              .select_related('article', 'product'))
        out = []
        for s in qs:
            src = s.source
            if s.kind == 'article' and (src is None or src.status != 'published'):
                continue
            if s.kind in ('magazine', 'product') and (src is None or not src.is_active):
                continue
            out.append(s)
        return out

    def display(self):
        """Everything the template needs, with blanks filled in from the article / issue / product."""
        from django.utils.html import strip_tags
        src = self.source
        d = {'kind': self.kind, 'eyebrow': self.eyebrow, 'title': self.title, 'text': self.text,
             'button_text': self.button_text, 'url': self.button_url, 'bg': self.image.url if self.image else '',
             'side': '', 'blur': False, 'position': self.image_position, 'obj': src,
             'phone_bg': self.phone_image.url if self.phone_image else (self.image.url if self.image else ''),
             'phone_side': False, 'phone_plain': False}
        if self.kind == 'article' and src:
            cat = src.categories.first()
            d['eyebrow'] = d['eyebrow'] or ' · '.join(x for x in (cat.name if cat else '', src.historical_period or '') if x)
            d['title'] = d['title'] or src.title
            d['text'] = d['text'] or strip_tags(src.excerpt or '')
            d['url'] = d['url'] or src.get_absolute_url()
            if not d['bg'] and src.featured_image:
                d['bg'] = src.featured_image.url
        elif src is not None:
            if src.product_type == 'magazine':
                d['eyebrow'] = d['eyebrow'] or ('The Reverse Times Magazine' + (f' · {src.issue_label}' if src.issue_label else ''))
                d['text'] = d['text'] or (src.subtitle or strip_tags(src.description or '')[:220])
            else:
                d['eyebrow'] = d['eyebrow'] or ('ইতিহাস পরুন গায়ে' if src.product_type == 'merch' else 'পুরনো দিনের জিনিস')
                d['text'] = d['text'] or strip_tags(src.description or '')[:200]
            d['title'] = d['title'] or src.title
            d['url'] = d['url'] or src.get_absolute_url()
            d['side'] = src.image.url if src.image else ''
            if not d['bg']:
                d['bg'], d['blur'] = d['side'], True
            if self.phone_display == 'product':
                d['phone_side'] = bool(d['side'])
                d['phone_bg'] = self.phone_image.url if self.phone_image else ''  # empty → same as desktop
            else:
                d['phone_plain'] = not d['phone_bg']  # no custom picture → no picture on phones
        return d
