from django.db import models
from django.urls import reverse, NoReverseMatch
from django.template.defaultfilters import truncatechars
from django.utils.text import slugify
from meta.models import ModelMeta
from django.utils import timezone
from django.core.exceptions import ValidationError
from imagekit.models import ImageSpecField
from imagekit.processors import ResizeToFill, ResizeToFit
from cms.image_mixin import ImageProcessingMixin
import re
import mimetypes
from django.contrib.auth.models import User

class Region(models.Model):
    name = models.CharField(max_length=100, help_text="Full name of the region, e.g., United Kingdom")
    code = models.CharField(max_length=10, unique=True, help_text="URL prefix code, e.g., 'uk', 'ca', 'uae'")
    is_active = models.BooleanField(default=True)
    is_default = models.BooleanField(default=False, help_text="Set one region as default")
    flag_icon = models.CharField(max_length=50, blank=True, help_text="CSS class for flag icon if available")

    def __str__(self):
        return self.name

class UserProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
    managed_region = models.ForeignKey(
        Region, 
        on_delete=models.SET_NULL, 
        null=True, 
        blank=True, 
        help_text="If set, this user can only manage content for this specific region. Leave blank for global access (superusers usually)."
    )

    def __str__(self):
        return f"{self.user.username} Profile"


class CompanySettings(models.Model):
    """Global company settings for contact information and branding"""
    company_name = models.CharField(max_length=200, default="XinfinityGroup")
    phone = models.CharField(max_length=20, default="01515 425 016")
    emergency_phone = models.CharField(max_length=20, default="01515 425 016", help_text="24/7 Emergency Line")
    email = models.EmailField(default="info@xinfinitygroup.com")
    street_address = models.CharField(max_length=255, default="67-83 Norfolk Street")
    address_line_2 = models.CharField(max_length=255, blank=True, default="Queens Dock Business Centre")
    building_name = models.CharField(max_length=100, default="Shipwright House", blank=True)
    office_number = models.CharField(max_length=50, default="M8 Office No4", blank=True)
    city = models.CharField(max_length=100, default="Liverpool")
    region = models.CharField(max_length=100, default="England")
    postal_code = models.CharField(max_length=20, default="L1 0BG")
    country = models.CharField(max_length=100, default="GB")
    regions = models.ManyToManyField(
        Region,
        blank=True,
        help_text="Regions where these settings apply. Leave empty for global/default.",
    )
    
    # Social media
    facebook_url = models.URLField(blank=True, default="https://www.facebook.com/xinfinitygroup")
    linkedin_url = models.URLField(blank=True, default="https://www.linkedin.com/company/xinfinitygroup")
    twitter_url = models.URLField(blank=True, default="https://www.twitter.com/xinfinitygroup")
    instagram_url = models.URLField(blank=True, default="https://www.instagram.com/xinfinitygroup")
    
    # Business info
    founded_year = models.IntegerField(default=2004)
    description = models.TextField(default="Leading facilities management services provider offering comprehensive security, cleaning, and facility management solutions.")
    
    updated_at = models.DateTimeField(auto_now=True)
    
    class Meta:
        verbose_name_plural = "Company Settings"
    
    def __str__(self):
        return f"{self.company_name} Settings"
    
    def get_full_address(self):
        """Return formatted full address"""
        parts = [
            self.building_name,
            self.office_number,
            self.street_address,
            self.address_line_2,
            self.city,
            self.postal_code,
        ]
        return ", ".join([p for p in parts if p])


class FooterSettings(models.Model):
    """Site-wide footer settings."""
    contact_heading = models.CharField(max_length=100, default="Get In Touch")
    office_label = models.CharField(max_length=100, default="Head Office")
    description = models.TextField(
        default="Integrated facilities management, security, cleaning, and property services for commercial, industrial, and public sector environments."
    )
    badge_one_label = models.CharField(max_length=100, default="ISO 9001 Certified")
    badge_one_icon = models.CharField(max_length=50, default="shield-check", help_text="Lucide icon name")
    badge_two_label = models.CharField(max_length=100, default="Industry Leader")
    badge_two_icon = models.CharField(max_length=50, default="award", help_text="Lucide icon name")
    business_hours = models.CharField(max_length=200, default="Mon - Fri: 9:00 AM - 6:00 PM")
    emergency_hours = models.CharField(max_length=200, default="Emergency: 24/7 Available")
    regions = models.ManyToManyField(
        Region,
        blank=True,
        help_text="Regions where these footer settings apply. Leave empty for global/default.",
    )

    def __str__(self):
        return "Footer Settings"


class FooterLinkGroup(models.Model):
    LOCATION_CHOICES = (
        ("main", "Main Footer"),
        ("bottom", "Bottom Bar"),
    )
    title = models.CharField(max_length=100)
    location = models.CharField(max_length=20, choices=LOCATION_CHOICES, default="main")
    order = models.PositiveIntegerField(default=0)
    is_active = models.BooleanField(default=True)

    class Meta:
        ordering = ["location", "order"]

    def __str__(self):
        return self.title


class FooterLink(models.Model):
    group = models.ForeignKey(FooterLinkGroup, related_name="links", on_delete=models.CASCADE)
    label = models.CharField(max_length=100)
    url_name = models.CharField(max_length=100, blank=True, help_text="Django URL name (optional)")
    custom_url = models.URLField(blank=True, help_text="Custom URL if not using url_name")
    open_in_new = models.BooleanField(default=False)
    order = models.PositiveIntegerField(default=0)
    is_active = models.BooleanField(default=True)

    class Meta:
        ordering = ["order"]

    def __str__(self):
        return f"{self.group.title} - {self.label}"

    def clean(self):
        """Validate that a usable URL is provided."""
        from django.urls import reverse, NoReverseMatch

        if not self.url_name and not self.custom_url:
            raise ValidationError("Provide either a URL name or a custom URL.")

        if self.url_name:
            try:
                reverse(self.url_name)
            except NoReverseMatch as exc:
                raise ValidationError(
                    {"url_name": "Unknown URL name. Use a valid Django URL name from cms/urls.py."}
                ) from exc


class SeoMixin(ModelMeta):
    """Base mixin for SEO-enabled models"""
    _metadata = {
        'title': 'get_meta_title',
        'description': 'get_meta_description',
        'keywords': 'get_meta_keywords',
        'image': 'get_meta_image_url',
        'canonical_url': 'get_canonical_url',
    }

    def get_meta_title(self):
        return self.meta_title or self.title

    def get_meta_description(self):
        return self.meta_description

    def get_meta_keywords(self):
        return self.meta_keywords.split(',') if self.meta_keywords else []

    def get_meta_image_url(self):
        if self.meta_image:
            return self.meta_image.url
        return None

    def get_canonical_url(self):
        if self.meta_canonical_url:
            return self.meta_canonical_url
        try:
            return self.get_absolute_url()
        except NoReverseMatch:
            return ''

    def generate_meta_description(self, source_text, max_length=160):
        """Generate a meta description using simple truncation."""
        if not source_text:
            return ''
        
        # Clean the input text
        clean_text = re.sub(r'<[^>]+>', '', source_text)
        clean_text = ' '.join(clean_text.split())
        
        # Simple truncation - much faster than sumy
        return truncatechars(clean_text, max_length)

    def generate_meta_keywords(self, source_text, max_keywords=10):
        """Generate meta keywords efficiently."""
        if not source_text:
            return ''
            
        words = re.findall(r'\w+', source_text.lower()[:1000])  # Limit input
        stop_words = {'the', 'a', 'an', 'and', 'or', 'but', 'in', 'on', 'at', 'to', 'for', 'with'}
        keywords = list(dict.fromkeys([word for word in words if word not in stop_words and len(word) > 3]))
        return ', '.join(keywords[:max_keywords])

    def save(self, *args, **kwargs):
        """Override save to auto-populate SEO fields only when needed."""
        # Auto-generate meta_title (max 100 chars)
        if not self.meta_title:
            self.meta_title = self.title[:100] if hasattr(self, 'title') else ''
        
        if not self.meta_description:
            content_text = getattr(self, 'content', '') or getattr(self, 'description', '')
            if content_text:
                self.meta_description = self.generate_meta_description(content_text)
        
        if not self.meta_keywords:
            content_text = getattr(self, 'content', '') or getattr(self, 'description', '')
            if content_text:
                self.meta_keywords = self.generate_meta_keywords(content_text)
        
        super().save(*args, **kwargs)

class Service(ImageProcessingMixin, SeoMixin, models.Model):
    title = models.CharField(max_length=200)
    slug = models.SlugField(unique=True, max_length=255, blank=True)
    description = models.TextField()
    image = models.ImageField(upload_to='services/', blank=True, null=True)
    image_alt = models.CharField(max_length=125, blank=True, help_text="Alt text for service image (SEO)")
    
    # Image fields to process
    image_fields = ['image', 'meta_image']
    # Optimized image specs for service image
    image_thumbnail = ImageSpecField(
        source='image',
        processors=[ResizeToFill(300, 200)],
        format='JPEG',
        options={'quality': 85}
    )
    image_medium = ImageSpecField(
        source='image',
        processors=[ResizeToFit(800, 600)],
        format='JPEG',
        options={'quality': 85}
    )
    
    # WebP optimized images
    image_thumbnail_webp = ImageSpecField(
        source='image',
        processors=[ResizeToFill(300, 200)],
        format='WEBP',
        options={'quality': 85}
    )
    image_webp = ImageSpecField(
        source='image',
        processors=[ResizeToFit(1200, 900)],
        format='WEBP',
        options={'quality': 90}
    )
    icon = models.CharField(max_length=50, help_text="Icon name from your icon set", blank=True)
    service_type = models.CharField(
        max_length=50,
        default='security',
        help_text="Select a service type: security, cleaning, staffing, logistics, risk-management, property, or one of the alt slugs."
    )
    is_published = models.BooleanField(default=True)
    regions = models.ManyToManyField(Region, blank=True, help_text="Regions where this service is available. Leave empty for all.")
    order = models.PositiveIntegerField(default=0)
    
    meta_title = models.CharField(max_length=100, blank=True, help_text="SEO Title (max 100 chars)")
    meta_description = models.TextField(max_length=160, blank=True, help_text="SEO Description (max 160 chars)")
    meta_keywords = models.CharField(max_length=255, blank=True, help_text="Comma-separated keywords")
    meta_image = models.ImageField(upload_to='seo_images/', blank=True, null=True, help_text="Image for social sharing")
    meta_canonical_url = models.URLField(blank=True, help_text="Canonical URL if different from this page")
    
    # Conversion Optimization Fields
    value_proposition = models.TextField(blank=True, help_text="Clear value proposition for this service")
    primary_cta_text = models.CharField(max_length=50, blank=True, default="Get Started", help_text="Primary CTA button text")
    primary_cta_url = models.CharField(max_length=255, blank=True, default="#contact", help_text="Primary CTA button URL")
    secondary_cta_text = models.CharField(max_length=50, blank=True, help_text="Secondary CTA button text (optional)")
    secondary_cta_url = models.CharField(max_length=255, blank=True, help_text="Secondary CTA button URL (optional)")
    certifications = models.TextField(blank=True, help_text="Comma-separated list of certifications")
    years_in_business = models.PositiveIntegerField(blank=True, null=True, help_text="Years of experience in this service")
    customer_count = models.PositiveIntegerField(blank=True, null=True, help_text="Number of customers served")
    uptime_guarantee = models.DecimalField(max_digits=5, decimal_places=2, blank=True, null=True, help_text="Uptime guarantee percentage (e.g., 99.8)")
    
    def get_absolute_url(self):
        try:
            return reverse('service_detail', kwargs={'slug': self.slug})
        except NoReverseMatch:
            print(f"Warning: NoReverseMatch for Service slug {self.slug}. Is 'service_detail' URL pattern defined?")
            return '/services/'
    
    def __str__(self):
        return self.title

    def _generate_unique_slug(self):
        if self.slug:
            base_slug = self.slug
        else:
            base_slug = slugify(self.title)
        slug = base_slug
        num = 1
        ModelClass = self.__class__
        while ModelClass.objects.filter(slug=slug).exclude(pk=self.pk).exists():
            slug = f"{base_slug}-{num}"
            num += 1
        return slug

    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = self._generate_unique_slug()
        super().save(*args, **kwargs)
    
    # Conversion Optimization Methods
    def get_value_proposition(self):
        """Get the value proposition for this service"""
        return self.value_proposition or self.description[:200]
    
    def get_primary_cta(self):
        """Get the primary call-to-action"""
        return {
            'text': self.primary_cta_text or 'Get Started',
            'url': self.primary_cta_url or '#contact',
            'style': 'primary',
        }
    
    def get_secondary_cta(self):
        """Get the secondary call-to-action"""
        if self.secondary_cta_text:
            return {
                'text': self.secondary_cta_text,
                'url': self.secondary_cta_url or '#contact',
                'style': 'secondary',
            }
        return None
    
    def get_trust_signals(self):
        """Get trust signals for this service"""
        signals = []
        
        if self.certifications:
            signals.append({
                'type': 'certifications',
                'content': self.certifications,
                'icon': 'award',
            })
        
        if self.years_in_business:
            signals.append({
                'type': 'experience',
                'content': f'{self.years_in_business}+ years in business',
                'icon': 'clock',
            })
        
        if self.customer_count:
            signals.append({
                'type': 'customers',
                'content': f'Trusted by {self.customer_count}+ customers',
                'icon': 'users',
            })
        
        if self.uptime_guarantee:
            signals.append({
                'type': 'uptime',
                'content': f'{self.uptime_guarantee}% uptime guarantee',
                'icon': 'shield-check',
            })
        
        return signals
    
    class Meta:
        ordering = ['order']
        indexes = [
            models.Index(fields=['is_published']),
            models.Index(fields=['order']),
            models.Index(fields=['service_type']),
            models.Index(fields=['slug']),
        ]

class TeamMember(ImageProcessingMixin, models.Model): # Not using SeoMixin or auto-slug for TeamMember
    name = models.CharField(max_length=100)
    position = models.CharField(max_length=100)
    bio = models.TextField(blank=True)
    photo = models.ImageField(upload_to='team/')
    photo_alt = models.CharField(max_length=125, blank=True, help_text="Alt text for photo (SEO)")
    
    # Image fields to process
    image_fields = ['photo']
    # Optimized image specs for photo
    photo_thumbnail = ImageSpecField(
        source='photo',
        processors=[ResizeToFill(150, 150)],
        format='JPEG',
        options={'quality': 85}
    )
    photo_medium = ImageSpecField(
        source='photo',
        processors=[ResizeToFit(400, 400)],
        format='JPEG',
        options={'quality': 85}
    )
    
    # WebP optimized images
    photo_thumbnail_webp = ImageSpecField(
        source='photo',
        processors=[ResizeToFill(150, 150)],
        format='WEBP',
        options={'quality': 85}
    )
    photo_webp = ImageSpecField(
        source='photo',
        processors=[ResizeToFit(800, 800)],
        format='WEBP',
        options={'quality': 90}
    )
    regions = models.ManyToManyField(Region, blank=True, help_text="Regions where this team member is active. Leave empty for all.")
    order = models.PositiveIntegerField(default=0)
    created_at = models.DateTimeField(auto_now_add=True, null=True, blank=True)
    updated_at = models.DateTimeField(auto_now=True, null=True, blank=True)
    
    def __str__(self):
        return self.name
    
    def safe_photo_webp_url(self):
        """Return the photo WebP URL, or None if the source file is missing.
        Prevents a single missing media file from causing the whole page to 500.
        """
        if not self.photo:
            return None
        try:
            return self.photo_webp.url
        except Exception:
            return None
    
    class Meta:
        ordering = ['order']
        indexes = [
            models.Index(fields=['order']),
            models.Index(fields=['created_at']),
        ]

class Testimonial(ImageProcessingMixin, models.Model):
    name = models.CharField(max_length=100)
    position = models.CharField(max_length=100, blank=True)
    company = models.CharField(max_length=100, blank=True)
    quote = models.TextField()
    photo = models.ImageField(upload_to='testimonials/', blank=True, null=True)
    photo_alt = models.CharField(max_length=125, blank=True, help_text="Alt text for photo (SEO)")
    
    # Image fields to process
    image_fields = ['photo']
    # Optimized image specs for photo
    photo_thumbnail = ImageSpecField(
        source='photo',
        processors=[ResizeToFill(100, 100)],
        format='JPEG',
        options={'quality': 85}
    )
    
    # WebP optimized images
    photo_thumbnail_webp = ImageSpecField(
        source='photo',
        processors=[ResizeToFill(100, 100)],
        format='WEBP',
        options={'quality': 85}
    )
    photo_webp = ImageSpecField(
        source='photo',
        processors=[ResizeToFit(400, 400)],
        format='WEBP',
        options={'quality': 90}
    )
    is_published = models.BooleanField(default=True)
    regions = models.ManyToManyField(Region, blank=True, help_text="Regions for this testimonial. Leave empty for all.")
    
    class Meta:
        indexes = [
            models.Index(fields=['is_published']),
        ]

    def __str__(self):
        return f"{self.name} - {self.company}"

class About(ImageProcessingMixin, SeoMixin, models.Model):
    title = models.CharField(max_length=200)
    slug = models.SlugField(unique=True, max_length=255, blank=True)
    content = models.TextField()
    image = models.ImageField(upload_to='about/', blank=True, null=True)
    image_alt = models.CharField(max_length=125, blank=True, help_text="Alt text for image (SEO)")
    
    # Image fields to process
    image_fields = ['image', 'meta_image']
    # Optimized image specs
    image_thumbnail = ImageSpecField(
        source='image',
        processors=[ResizeToFill(300, 200)],
        format='JPEG',
        options={'quality': 85}
    )
    image_medium = ImageSpecField(
        source='image',
        processors=[ResizeToFit(800, 600)],
        format='JPEG',
        options={'quality': 85}
    )
    is_published = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    meta_title = models.CharField(max_length=100, blank=True, help_text="SEO Title (max 100 chars)")
    meta_description = models.TextField(max_length=160, blank=True, help_text="SEO Description (max 160 chars)")
    meta_keywords = models.CharField(max_length=255, blank=True, help_text="Comma-separated keywords")
    meta_image = models.ImageField(upload_to='seo_images/', blank=True, null=True, help_text="Image for social sharing")
    meta_canonical_url = models.URLField(blank=True, help_text="Canonical URL if different from this page")

    def get_absolute_url(self):
        try:
            return reverse('about')
        except NoReverseMatch:
            print(f"Warning: NoReverseMatch for About slug {self.slug}. Is 'about' URL pattern defined?")
            return '/about/'

    def __str__(self):
        return self.title

    def _generate_unique_slug(self):
        if self.slug:
            base_slug = self.slug
        else:
            base_slug = slugify(self.title)
        slug = base_slug
        num = 1
        ModelClass = self.__class__
        while ModelClass.objects.filter(slug=slug).exclude(pk=self.pk).exists():
            slug = f"{base_slug}-{num}"
            num += 1
        return slug

    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = self._generate_unique_slug()
        super().save(*args, **kwargs)

    class Meta:
        ordering = ['created_at']

class Contact(models.Model):
    """Model to store contact form submissions."""
    name = models.CharField(max_length=100, help_text="Full name of the person submitting the form")
    email = models.EmailField(max_length=255, help_text="Contact email address")
    phone = models.CharField(
        max_length=20,
        blank=True,
        help_text="Contact phone number (optional)"
    )
    subject = models.CharField(
        max_length=200,
        blank=True,
        help_text="Subject of the message (optional)"
    )
    message = models.TextField(help_text="Message content")
    created_at = models.DateTimeField(default=timezone.now, help_text="Timestamp when the form was submitted")
    is_resolved = models.BooleanField(
        default=False,
        help_text="Indicates if the inquiry has been addressed"
    )

    # Visitor intelligence captured at submission time (anti-spam / forensics)
    ip_address = models.GenericIPAddressField(null=True, blank=True, help_text="Submitter IP address")
    country_code = models.CharField(max_length=2, blank=True, help_text="ISO country code from geolocation")
    country_name = models.CharField(max_length=100, blank=True)
    city = models.CharField(max_length=100, blank=True)
    user_agent = models.TextField(blank=True, help_text="Raw user agent string")
    is_spam = models.BooleanField(default=False, help_text="Flagged as spam/fake by automatic checks")
    spam_reason = models.CharField(max_length=255, blank=True, help_text="Why the submission was flagged")

    class Meta:
        verbose_name = "Contact Form Submission"
        verbose_name_plural = "Contact Form Submissions"
        ordering = ['-created_at']
        indexes = [
            models.Index(fields=['ip_address']),
            models.Index(fields=['is_spam']),
        ]

    def __str__(self):
        return f"{self.name} - {self.email} ({self.created_at.strftime('%Y-%m-%d')})"


class BlockedIP(models.Model):
    """An IP address (or range) that is denied access to the site.

    Blocks are checked by ``cms.visitor_middleware.IPBlockMiddleware`` on every
    request and are also used to reject contact-form submissions from abusive
    sources. Entries can be created manually from the admin or automatically
    when a visitor trips an anti-spam rule.
    """

    BLOCK_TYPE_CHOICES = (
        ('single', 'Single IP address'),
        ('cidr', 'CIDR range (e.g. 203.0.113.0/24)'),
        ('prefix', 'IP prefix (e.g. 203.0.113.)'),
    )

    SOURCE_CHOICES = (
        ('manual', 'Manual'),
        ('auto', 'Automatic'),
        ('contact_form', 'Contact form'),
        ('rate_limit', 'Rate limit'),
    )

    ip_address = models.CharField(
        max_length=64,
        unique=True,
        help_text="IP address, CIDR range or prefix to block",
    )
    block_type = models.CharField(max_length=20, choices=BLOCK_TYPE_CHOICES, default='single')
    reason = models.CharField(max_length=255, blank=True, help_text="Short reason shown in listings")
    source = models.CharField(max_length=20, choices=SOURCE_CHOICES, default='manual')
    notes = models.TextField(blank=True, help_text="Internal notes about this block")
    is_active = models.BooleanField(default=True, help_text="Disable to temporarily allow this address")
    hit_count = models.PositiveIntegerField(default=0, help_text="Number of requests blocked")
    last_hit = models.DateTimeField(null=True, blank=True)
    created_by = models.ForeignKey(
        User, on_delete=models.SET_NULL, null=True, blank=True, related_name='blocked_ips'
    )
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    expires_at = models.DateTimeField(
        null=True, blank=True, help_text="Optional expiry. Leave blank for a permanent block."
    )

    class Meta:
        verbose_name = "Blocked IP"
        verbose_name_plural = "Blocked IPs"
        ordering = ['-created_at']
        indexes = [
            models.Index(fields=['is_active']),
            models.Index(fields=['ip_address']),
            models.Index(fields=['expires_at']),
        ]

    def __str__(self):
        return f"{self.ip_address} ({self.get_source_display()})"

    @property
    def is_expired(self) -> bool:
        return bool(self.expires_at and self.expires_at <= timezone.now())

    def is_effective(self) -> bool:
        """Return True when the block is active and not expired."""
        return self.is_active and not self.is_expired

    def matches(self, ip_address: str) -> bool:
        """Return True when ``ip_address`` is covered by this block."""
        if not ip_address:
            return False

        try:
            if self.block_type == 'cidr' or '/' in self.ip_address:
                import ipaddress

                network = ipaddress.ip_network(self.ip_address.strip(), strict=False)
                return ipaddress.ip_address(ip_address.strip()) in network

            if self.block_type == 'prefix':
                return ip_address.startswith(self.ip_address)

            return ip_address.strip() == self.ip_address.strip()
        except (ValueError, TypeError):
            return False


class VisitorSession(models.Model):
    """Aggregated, per-visitor analytics record.

    One row is maintained per visitor fingerprint (Django session for humans,
    IP+user-agent hash for crawlers). It stores everything we know about the
    visitor: network identity, geolocation, device and browsing behaviour.
    """

    session_key = models.CharField(max_length=64, unique=True, db_index=True)
    ip_address = models.GenericIPAddressField(null=True, blank=True)
    ip_version = models.PositiveSmallIntegerField(default=0)
    is_bot = models.BooleanField(default=False)
    is_blocked = models.BooleanField(default=False)

    # Geolocation / network intelligence
    country_code = models.CharField(max_length=2, blank=True)
    country_name = models.CharField(max_length=100, blank=True)
    region = models.CharField(max_length=100, blank=True)
    city = models.CharField(max_length=100, blank=True)
    postal_code = models.CharField(max_length=20, blank=True)
    latitude = models.FloatField(null=True, blank=True)
    longitude = models.FloatField(null=True, blank=True)
    timezone_name = models.CharField(max_length=64, blank=True)
    isp = models.CharField(max_length=200, blank=True, help_text="Internet service provider")
    org = models.CharField(max_length=200, blank=True, help_text="Organisation / ASN owner")
    asn = models.CharField(max_length=50, blank=True)
    is_proxy = models.BooleanField(default=False)
    is_hosting = models.BooleanField(default=False)

    # Device / client
    user_agent = models.TextField(blank=True)
    device_type = models.CharField(max_length=20, blank=True, help_text="desktop, mobile, tablet, bot")
    browser = models.CharField(max_length=50, blank=True)
    os = models.CharField(max_length=50, blank=True)

    # Navigation
    referer = models.CharField(max_length=500, blank=True)
    landing_path = models.CharField(max_length=500, blank=True)
    last_path = models.CharField(max_length=500, blank=True)
    region_code = models.CharField(max_length=10, blank=True)

    page_views = models.PositiveIntegerField(default=0)
    first_seen = models.DateTimeField(auto_now_add=True)
    last_seen = models.DateTimeField(default=timezone.now)

    class Meta:
        verbose_name = "Visitor Session"
        verbose_name_plural = "Visitor Sessions"
        ordering = ['-last_seen']
        indexes = [
            models.Index(fields=['last_seen']),
            models.Index(fields=['ip_address']),
            models.Index(fields=['country_code']),
            models.Index(fields=['is_bot']),
        ]

    def __str__(self):
        location = self.city or self.country_name or 'Unknown'
        return f"{self.ip_address or 'unknown'} - {location}"

    @property
    def is_online(self) -> bool:
        return (timezone.now() - self.last_seen).total_seconds() < 300

    @property
    def location_display(self) -> str:
        parts = [p for p in (self.city, self.region, self.country_name) if p]
        return ', '.join(parts) if parts else 'Unknown'


class VisitorPageView(models.Model):
    """A single page view recorded for a :class:`VisitorSession`."""

    session = models.ForeignKey(
        VisitorSession, on_delete=models.CASCADE, related_name='pageviews'
    )
    ip_address = models.GenericIPAddressField(null=True, blank=True)
    path = models.CharField(max_length=500)
    method = models.CharField(max_length=8, default='GET')
    status_code = models.PositiveSmallIntegerField(null=True, blank=True)
    referer = models.CharField(max_length=500, blank=True)
    user_agent = models.TextField(blank=True)
    viewed_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        verbose_name = "Visitor Page View"
        verbose_name_plural = "Visitor Page Views"
        ordering = ['-viewed_at']
        indexes = [
            models.Index(fields=['viewed_at']),
            models.Index(fields=['path']),
        ]

    def __str__(self):
        return f"{self.path} @ {self.viewed_at:%Y-%m-%d %H:%M}"


class RedirectLog(models.Model):
    """Log of geo-redirect events for monitoring and analytics.
    
    This model tracks all redirect events triggered by the geo-targeting system,
    enabling monitoring of redirect patterns, geolocation accuracy, and system performance.
    """
    source_ip = models.GenericIPAddressField(
        help_text="IP address of the visitor"
    )
    detected_country = models.CharField(
        max_length=2,
        help_text="ISO 3166-1 alpha-2 country code detected by geolocation"
    )
    target_url = models.URLField(
        help_text="URL the visitor was redirected to"
    )
    status_code = models.IntegerField(
        help_text="HTTP status code used for the redirect (301 or 302)"
    )
    user_agent = models.TextField(
        blank=True,
        help_text="User agent string from the request"
    )
    referer = models.URLField(
        blank=True,
        help_text="Referer URL from the request"
    )
    timestamp = models.DateTimeField(
        auto_now_add=True,
        help_text="When the redirect occurred"
    )

    class Meta:
        verbose_name = "Redirect Log"
        verbose_name_plural = "Redirect Logs"
        ordering = ['-timestamp']
        indexes = [
            models.Index(fields=['timestamp']),
            models.Index(fields=['detected_country']),
            models.Index(fields=['source_ip']),
        ]

    def __str__(self):
        return f"{self.source_ip} -> {self.detected_country} ({self.timestamp.strftime('%Y-%m-%d %H:%M:%S')})"


# Link Building and Outreach Models

class OutreachCampaign(models.Model):
    """Model for managing link building outreach campaigns."""
    
    CAMPAIGN_STATUS_CHOICES = [
        ('planning', 'Planning'),
        ('active', 'Active'),
        ('paused', 'Paused'),
        ('completed', 'Completed'),
        ('archived', 'Archived'),
    ]
    
    name = models.CharField(max_length=255, unique=True)
    description = models.TextField(blank=True)
    status = models.CharField(
        max_length=20,
        choices=CAMPAIGN_STATUS_CHOICES,
        default='planning'
    )
    
    # Campaign details
    target_keywords = models.JSONField(default=list, help_text="Target keywords for this campaign")
    target_da_min = models.IntegerField(default=40, help_text="Minimum domain authority target")
    estimated_links = models.IntegerField(default=0, help_text="Estimated number of links")
    
    # Timeline
    start_date = models.DateTimeField(null=True, blank=True)
    end_date = models.DateTimeField(null=True, blank=True)
    
    # Tracking
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    
    # Results
    links_acquired = models.IntegerField(default=0)
    contacts_reached = models.IntegerField(default=0)
    response_rate = models.FloatField(default=0.0, help_text="Response rate percentage")
    
    class Meta:
        ordering = ['-created_at']
        verbose_name = 'Outreach Campaign'
        verbose_name_plural = 'Outreach Campaigns'
    
    def __str__(self):
        return f"{self.name} ({self.status})"
    
    def get_duration_days(self):
        """Get campaign duration in days."""
        if self.start_date and self.end_date:
            return (self.end_date - self.start_date).days
        return None
    
    def get_success_rate(self):
        """Calculate success rate (links acquired / contacts reached)."""
        if self.contacts_reached > 0:
            return (self.links_acquired / self.contacts_reached) * 100
        return 0.0
    
    def is_active(self):
        """Check if campaign is currently active."""
        if self.status != 'active':
            return False
        
        if self.start_date and self.start_date > timezone.now():
            return False
        
        if self.end_date and self.end_date < timezone.now():
            return False
        
        return True


class OutreachContact(models.Model):
    """Model for managing outreach contacts."""
    
    CONTACT_TYPE_CHOICES = [
        ('editor', 'Editor'),
        ('publisher', 'Publisher'),
        ('author', 'Author'),
        ('webmaster', 'Webmaster'),
        ('owner', 'Owner'),
        ('other', 'Other'),
    ]
    
    campaign = models.ForeignKey(
        OutreachCampaign,
        on_delete=models.CASCADE,
        related_name='contacts'
    )
    
    # Contact information
    name = models.CharField(max_length=255)
    email = models.EmailField()
    publication = models.CharField(max_length=255)
    domain = models.CharField(max_length=255, blank=True)
    domain_authority = models.IntegerField(default=0)
    contact_type = models.CharField(
        max_length=20,
        choices=CONTACT_TYPE_CHOICES,
        default='editor'
    )
    
    # Contact details
    website_url = models.URLField(blank=True)
    phone = models.CharField(max_length=20, blank=True)
    notes = models.TextField(blank=True)
    
    # Outreach tracking
    outreach_status = models.CharField(
        max_length=20,
        choices=[
            ('not_contacted', 'Not Contacted'),
            ('contacted', 'Contacted'),
            ('responded', 'Responded'),
            ('link_acquired', 'Link Acquired'),
            ('rejected', 'Rejected'),
            ('no_response', 'No Response'),
        ],
        default='not_contacted'
    )
    
    # Outreach history
    first_contact_date = models.DateTimeField(null=True, blank=True)
    last_contact_date = models.DateTimeField(null=True, blank=True)
    contact_count = models.IntegerField(default=0)
    
    # Results
    link_acquired = models.BooleanField(default=False)
    link_url = models.URLField(blank=True)
    link_anchor_text = models.CharField(max_length=255, blank=True)
    link_acquired_date = models.DateTimeField(null=True, blank=True)
    
    # Metadata
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    
    class Meta:
        ordering = ['-domain_authority', 'name']
        verbose_name = 'Outreach Contact'
        verbose_name_plural = 'Outreach Contacts'
        unique_together = ['campaign', 'email']
    
    def __str__(self):
        return f"{self.name} ({self.publication})"
    
    def mark_contacted(self):
        """Mark contact as contacted."""
        self.outreach_status = 'contacted'
        self.first_contact_date = self.first_contact_date or timezone.now()
        self.last_contact_date = timezone.now()
        self.contact_count += 1
        self.save()
    
    def mark_responded(self):
        """Mark contact as responded."""
        self.outreach_status = 'responded'
        self.last_contact_date = timezone.now()
        self.save()
    
    def mark_link_acquired(self, link_url, anchor_text=""):
        """Mark link as acquired."""
        self.outreach_status = 'link_acquired'
        self.link_acquired = True
        self.link_url = link_url
        self.link_anchor_text = anchor_text
        self.link_acquired_date = timezone.now()
        self.save()
    
    def mark_rejected(self):
        """Mark contact as rejected."""
        self.outreach_status = 'rejected'
        self.last_contact_date = timezone.now()
        self.save()
    
    def get_days_since_contact(self):
        """Get days since last contact."""
        if self.last_contact_date:
            return (timezone.now() - self.last_contact_date).days
        return None


class OutreachEmail(models.Model):
    """Model for tracking outreach emails."""
    
    contact = models.ForeignKey(
        OutreachContact,
        on_delete=models.CASCADE,
        related_name='emails'
    )
    
    # Email details
    subject = models.CharField(max_length=255)
    body = models.TextField()
    template_used = models.CharField(max_length=100, blank=True)
    
    # Tracking
    sent_at = models.DateTimeField(auto_now_add=True)
    opened = models.BooleanField(default=False)
    opened_at = models.DateTimeField(null=True, blank=True)
    clicked = models.BooleanField(default=False)
    clicked_at = models.DateTimeField(null=True, blank=True)
    
    # Response
    replied = models.BooleanField(default=False)
    reply_date = models.DateTimeField(null=True, blank=True)
    reply_text = models.TextField(blank=True)
    
    class Meta:
        ordering = ['-sent_at']
        verbose_name = 'Outreach Email'
        verbose_name_plural = 'Outreach Emails'
    
    def __str__(self):
        return f"Email to {self.contact.name} - {self.sent_at.strftime('%Y-%m-%d')}"


class LinkAcquisition(models.Model):
    """Model for tracking acquired links."""
    
    campaign = models.ForeignKey(
        OutreachCampaign,
        on_delete=models.CASCADE,
        related_name='acquired_links'
    )
    contact = models.ForeignKey(
        OutreachContact,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='acquired_links'
    )
    
    # Link details
    source_url = models.URLField()
    target_url = models.URLField()
    anchor_text = models.CharField(max_length=255)
    link_type = models.CharField(
        max_length=20,
        choices=[
            ('dofollow', 'Dofollow'),
            ('nofollow', 'Nofollow'),
            ('unknown', 'Unknown'),
        ],
        default='unknown'
    )
    
    # Source information
    source_domain = models.CharField(max_length=255)
    source_domain_authority = models.IntegerField(default=0)
    source_page_authority = models.IntegerField(default=0)
    
    # Acquisition details
    acquired_date = models.DateTimeField()
    verified_date = models.DateTimeField(null=True, blank=True)
    is_verified = models.BooleanField(default=False)
    
    # Metadata
    notes = models.TextField(blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    
    class Meta:
        ordering = ['-acquired_date']
        verbose_name = 'Link Acquisition'
        verbose_name_plural = 'Link Acquisitions'
    
    def __str__(self):
        return f"Link from {self.source_domain} to {self.target_url}"
    
    def verify_link(self):
        """Mark link as verified."""
        self.is_verified = True
        self.verified_date = timezone.now()
        self.save()


# Google Business Profile Models

class GoogleBusinessProfile(models.Model):
    """Model for managing Google Business Profile information."""
    
    BUSINESS_TYPE_CHOICES = [
        ('local_business', 'Local Business'),
        ('service_area_business', 'Service Area Business'),
        ('online_business', 'Online Business'),
    ]
    
    # Basic Information
    business_name = models.CharField(max_length=255, help_text="Official business name")
    business_type = models.CharField(
        max_length=50,
        choices=BUSINESS_TYPE_CHOICES,
        default='service_area_business',
        help_text="Type of business"
    )
    description = models.TextField(help_text="Business description (up to 750 characters)")
    
    # Contact Information
    phone = models.CharField(max_length=20, help_text="Primary business phone number")
    email = models.EmailField(help_text="Business email address")
    website = models.URLField(help_text="Business website URL")
    
    # Address Information
    street_address = models.CharField(max_length=255, help_text="Street address")
    city = models.CharField(max_length=100, help_text="City")
    state_province = models.CharField(max_length=100, help_text="State or province")
    postal_code = models.CharField(max_length=20, help_text="Postal code")
    country = models.CharField(max_length=100, help_text="Country")
    
    # Service Areas (for service area businesses)
    service_areas = models.JSONField(
        default=list,
        blank=True,
        help_text="List of service areas (cities/regions)"
    )
    
    # Business Hours
    business_hours = models.JSONField(
        default=dict,
        blank=True,
        help_text="Business hours by day of week"
    )
    
    # Service Categories
    service_categories = models.JSONField(
        default=list,
        help_text="Primary and secondary service categories"
    )
    
    # Attributes
    attributes = models.JSONField(
        default=dict,
        blank=True,
        help_text="Business attributes (e.g., wheelchair accessible, accepts online orders)"
    )
    
    # Profile Status
    is_verified = models.BooleanField(default=False, help_text="Is the profile verified?")
    verification_date = models.DateTimeField(null=True, blank=True)
    
    # Metadata
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    last_synced = models.DateTimeField(null=True, blank=True, help_text="Last sync with Google")
    
    class Meta:
        verbose_name = 'Google Business Profile'
        verbose_name_plural = 'Google Business Profiles'
        ordering = ['-created_at']
    
    def __str__(self):
        return f"{self.business_name} - {self.city}"
    
    def get_full_address(self):
        """Get formatted full address."""
        return f"{self.street_address}, {self.city}, {self.state_province} {self.postal_code}, {self.country}"
    
    def is_complete(self):
        """Check if profile has all required information."""
        required_fields = [
            self.business_name,
            self.phone,
            self.website,
            self.street_address,
            self.city,
            self.country,
            self.description,
        ]
        return all(required_fields)


class GBPPhoto(ImageProcessingMixin, models.Model):
    """Model for managing Google Business Profile photos."""
    
    PHOTO_TYPE_CHOICES = [
        ('profile', 'Profile Photo'),
        ('cover', 'Cover Photo'),
        ('business', 'Business Photo'),
        ('team', 'Team Photo'),
        ('product', 'Product Photo'),
        ('service', 'Service Photo'),
    ]
    
    profile = models.ForeignKey(
        GoogleBusinessProfile,
        on_delete=models.CASCADE,
        related_name='photos'
    )
    
    # Photo Information
    title = models.CharField(max_length=255, help_text="Photo title/caption")
    description = models.TextField(blank=True, help_text="Photo description")
    photo_type = models.CharField(
        max_length=50,
        choices=PHOTO_TYPE_CHOICES,
        default='business',
        help_text="Type of photo"
    )
    
    # Photo File
    image = models.ImageField(
        upload_to='gbp_photos/',
        help_text="Photo image (recommended: 1200x900px or larger)"
    )
    
    # Image fields to process
    image_fields = ['image']
    
    # Metadata
    is_published = models.BooleanField(default=True, help_text="Is photo published on GBP?")
    order = models.PositiveIntegerField(default=0, help_text="Display order")
    view_count = models.PositiveIntegerField(default=0, help_text="Number of views")
    
    # Timestamps
    uploaded_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    
    class Meta:
        verbose_name = 'GBP Photo'
        verbose_name_plural = 'GBP Photos'
        ordering = ['order', '-uploaded_at']
    
    def __str__(self):
        return f"{self.title} - {self.profile.business_name}"


class GBPPost(ImageProcessingMixin, models.Model):
    """Model for managing Google Business Profile posts and updates."""
    
    POST_TYPE_CHOICES = [
        ('update', 'Update'),
        ('offer', 'Offer/Promotion'),
        ('event', 'Event'),
        ('product', 'Product'),
        ('service', 'Service'),
    ]
    
    profile = models.ForeignKey(
        GoogleBusinessProfile,
        on_delete=models.CASCADE,
        related_name='posts'
    )
    
    # Post Information
    title = models.CharField(max_length=255, help_text="Post title")
    content = models.TextField(help_text="Post content (up to 1500 characters)")
    post_type = models.CharField(
        max_length=50,
        choices=POST_TYPE_CHOICES,
        default='update',
        help_text="Type of post"
    )
    
    # Post Details
    call_to_action = models.CharField(
        max_length=100,
        blank=True,
        choices=[
            ('learn_more', 'Learn More'),
            ('book_now', 'Book Now'),
            ('order_now', 'Order Now'),
            ('call_now', 'Call Now'),
            ('sign_up', 'Sign Up'),
            ('get_offer', 'Get Offer'),
        ],
        help_text="Call-to-action button"
    )
    cta_url = models.URLField(blank=True, help_text="URL for CTA button")
    
    # Offer/Event Details
    offer_code = models.CharField(max_length=50, blank=True, help_text="Promo/offer code")
    start_date = models.DateTimeField(null=True, blank=True, help_text="Start date for offer/event")
    end_date = models.DateTimeField(null=True, blank=True, help_text="End date for offer/event")
    
    # Media
    image = models.ImageField(
        upload_to='gbp_posts/',
        blank=True,
        null=True,
        help_text="Post image (optional)"
    )
    
    # Image fields to process
    image_fields = ['image']
    
    # Status
    is_published = models.BooleanField(default=True, help_text="Is post published?")
    
    # Engagement
    view_count = models.PositiveIntegerField(default=0, help_text="Number of views")
    click_count = models.PositiveIntegerField(default=0, help_text="Number of CTA clicks")
    phone_call_count = models.PositiveIntegerField(default=0, help_text="Number of phone calls")
    
    # Timestamps
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    published_at = models.DateTimeField(null=True, blank=True)
    
    class Meta:
        verbose_name = 'GBP Post'
        verbose_name_plural = 'GBP Posts'
        ordering = ['-published_at', '-created_at']
    
    def __str__(self):
        return f"{self.title} - {self.profile.business_name}"


class GBPReview(models.Model):
    """Model for tracking and managing Google Business Profile reviews."""
    
    RATING_CHOICES = [
        (1, '1 Star'),
        (2, '2 Stars'),
        (3, '3 Stars'),
        (4, '4 Stars'),
        (5, '5 Stars'),
    ]
    
    RESPONSE_STATUS_CHOICES = [
        ('not_responded', 'Not Responded'),
        ('responded', 'Responded'),
        ('archived', 'Archived'),
    ]
    
    profile = models.ForeignKey(
        GoogleBusinessProfile,
        on_delete=models.CASCADE,
        related_name='reviews'
    )
    
    # Review Information
    reviewer_name = models.CharField(max_length=255, help_text="Name of the reviewer")
    rating = models.IntegerField(
        choices=RATING_CHOICES,
        help_text="Review rating (1-5 stars)"
    )
    review_text = models.TextField(help_text="Review content")
    
    # Review Metadata
    review_date = models.DateTimeField(help_text="Date the review was posted")
    review_url = models.URLField(blank=True, help_text="URL to the review on Google")
    
    # Response
    response_status = models.CharField(
        max_length=50,
        choices=RESPONSE_STATUS_CHOICES,
        default='not_responded',
        help_text="Response status"
    )
    response_text = models.TextField(blank=True, help_text="Response to the review")
    response_date = models.DateTimeField(null=True, blank=True, help_text="Date response was posted")
    
    # Engagement
    helpful_count = models.PositiveIntegerField(default=0, help_text="Number of 'helpful' votes")
    
    # Timestamps
    synced_at = models.DateTimeField(auto_now_add=True, help_text="When review was synced")
    updated_at = models.DateTimeField(auto_now=True)
    
    class Meta:
        verbose_name = 'GBP Review'
        verbose_name_plural = 'GBP Reviews'
        ordering = ['-review_date']
    
    def __str__(self):
        return f"{self.reviewer_name} - {self.rating} Stars"
    
    def get_rating_display_stars(self):
        """Get star display for rating."""
        return '★' * self.rating + '☆' * (5 - self.rating)
    
    def is_responded(self):
        """Check if review has been responded to."""
        return self.response_status == 'responded'


# Local Citation and NAP Consistency Models

class LocalCitation(models.Model):
    """Model for tracking local business citations across directories."""
    
    DIRECTORY_CHOICES = [
        ('google_business', 'Google Business'),
        ('bing_places', 'Bing Places'),
        ('apple_maps', 'Apple Maps'),
        ('trustpilot', 'Trustpilot'),
        ('yelp', 'Yelp'),
        ('facilities_management_dir', 'Facilities Management Directory'),
        ('business_directory', 'Business Directory'),
        ('industry_association', 'Industry Association'),
        ('chamber_of_commerce', 'Chamber of Commerce'),
        ('local_directory', 'Local Directory'),
        ('other', 'Other'),
    ]
    
    CITATION_STATUS_CHOICES = [
        ('not_listed', 'Not Listed'),
        ('pending', 'Pending'),
        ('active', 'Active'),
        ('needs_update', 'Needs Update'),
        ('suspended', 'Suspended'),
        ('removed', 'Removed'),
    ]
    
    # Directory Information
    directory_name = models.CharField(
        max_length=255,
        help_text="Name of the directory"
    )
    directory_type = models.CharField(
        max_length=50,
        choices=DIRECTORY_CHOICES,
        help_text="Type of directory"
    )
    directory_url = models.URLField(
        help_text="URL of the directory"
    )
    
    # Citation Information
    business_name = models.CharField(
        max_length=255,
        help_text="Business name as listed in directory"
    )
    address = models.CharField(
        max_length=255,
        help_text="Address as listed in directory"
    )
    phone = models.CharField(
        max_length=20,
        help_text="Phone number as listed in directory"
    )
    website = models.URLField(
        blank=True,
        null=True,
        help_text="Website URL as listed in directory"
    )
    email = models.EmailField(
        blank=True,
        help_text="Email as listed in directory"
    )
    
    # Citation Status
    status = models.CharField(
        max_length=50,
        choices=CITATION_STATUS_CHOICES,
        default='not_listed',
        help_text="Current status of the citation"
    )
    
    # Citation Details
    citation_url = models.URLField(
        blank=True,
        null=True,
        help_text="Direct URL to the business listing"
    )
    listing_id = models.CharField(
        max_length=255,
        blank=True,
        null=True,
        help_text="Directory-specific listing ID"
    )
    
    # NAP Consistency
    nap_consistent = models.BooleanField(
        default=False,
        help_text="Is NAP (Name, Address, Phone) consistent with primary listing?"
    )
    nap_issues = models.JSONField(
        default=list,
        blank=True,
        help_text="List of NAP inconsistencies found"
    )
    
    # Verification
    is_verified = models.BooleanField(
        default=False,
        help_text="Has the citation been verified?"
    )
    verification_date = models.DateTimeField(
        null=True,
        blank=True,
        help_text="Date the citation was verified"
    )
    
    # Timestamps
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    last_checked = models.DateTimeField(
        null=True,
        blank=True,
        help_text="Last time citation was checked for consistency"
    )
    
    class Meta:
        verbose_name = 'Local Citation'
        verbose_name_plural = 'Local Citations'
        ordering = ['directory_type', 'directory_name']
        unique_together = ['directory_name', 'listing_id']
    
    def __str__(self):
        return f"{self.business_name} - {self.directory_name}"
    
    def check_nap_consistency(self, primary_name, primary_address, primary_phone):
        """Check if citation NAP matches primary business information."""
        issues = []
        
        if self.business_name.lower().strip() != primary_name.lower().strip():
            issues.append(f"Name mismatch: '{self.business_name}' vs '{primary_name}'")
        
        if self.address.lower().strip() != primary_address.lower().strip():
            issues.append(f"Address mismatch: '{self.address}' vs '{primary_address}'")
        
        if self.phone.replace('-', '').replace(' ', '') != primary_phone.replace('-', '').replace(' ', ''):
            issues.append(f"Phone mismatch: '{self.phone}' vs '{primary_phone}'")
        
        self.nap_issues = issues
        self.nap_consistent = len(issues) == 0
        self.last_checked = timezone.now()
        self.save()
        
        return self.nap_consistent
    
    def mark_verified(self):
        """Mark citation as verified."""
        self.is_verified = True
        self.verification_date = timezone.now()
        self.save()
    
    def mark_needs_update(self):
        """Mark citation as needing update."""
        self.status = 'needs_update'
        self.save()


class NAPConsistencyReport(models.Model):
    """Model for tracking NAP consistency audit reports."""
    
    REPORT_STATUS_CHOICES = [
        ('pending', 'Pending'),
        ('in_progress', 'In Progress'),
        ('completed', 'Completed'),
        ('archived', 'Archived'),
    ]
    
    # Report Information
    report_name = models.CharField(
        max_length=255,
        help_text="Name of the NAP consistency report"
    )
    description = models.TextField(
        blank=True,
        help_text="Description of the report"
    )
    
    # Primary Business Information
    primary_business_name = models.CharField(
        max_length=255,
        help_text="Primary business name to check against"
    )
    primary_address = models.CharField(
        max_length=255,
        help_text="Primary address to check against"
    )
    primary_phone = models.CharField(
        max_length=20,
        help_text="Primary phone number to check against"
    )
    
    # Report Status
    status = models.CharField(
        max_length=50,
        choices=REPORT_STATUS_CHOICES,
        default='pending',
        help_text="Current status of the report"
    )
    
    # Report Results
    total_citations = models.IntegerField(
        default=0,
        help_text="Total number of citations checked"
    )
    consistent_citations = models.IntegerField(
        default=0,
        help_text="Number of citations with consistent NAP"
    )
    inconsistent_citations = models.IntegerField(
        default=0,
        help_text="Number of citations with inconsistent NAP"
    )
    consistency_percentage = models.FloatField(
        default=0.0,
        help_text="Percentage of consistent citations"
    )
    
    # Report Details
    citations_checked = models.ManyToManyField(
        LocalCitation,
        blank=True,
        help_text="Citations included in this report"
    )
    
    # Timestamps
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    completed_at = models.DateTimeField(
        null=True,
        blank=True,
        help_text="When the report was completed"
    )
    
    class Meta:
        verbose_name = 'NAP Consistency Report'
        verbose_name_plural = 'NAP Consistency Reports'
        ordering = ['-created_at']
    
    def __str__(self):
        return f"{self.report_name} - {self.consistency_percentage}% Consistent"
    
    def calculate_consistency(self):
        """Calculate NAP consistency percentage."""
        citations = self.citations_checked.all()
        if not citations.exists():
            return 0.0
        
        consistent_count = citations.filter(nap_consistent=True).count()
        total_count = citations.count()
        
        self.total_citations = total_count
        self.consistent_citations = consistent_count
        self.inconsistent_citations = total_count - consistent_count
        self.consistency_percentage = (consistent_count / total_count * 100) if total_count > 0 else 0.0
        self.save()
        
        return self.consistency_percentage
    
    def mark_completed(self):
        """Mark report as completed."""
        self.status = 'completed'
        self.completed_at = timezone.now()
        self.save()


# Thought Leadership Models

class ResearchProject(models.Model):
    """Model for tracking research projects and surveys."""
    
    RESEARCH_TYPE_CHOICES = [
        ('survey', 'Industry Survey'),
        ('study', 'Research Study'),
        ('report', 'Industry Report'),
        ('whitepaper', 'Whitepaper'),
        ('case_study', 'Case Study'),
        ('benchmark', 'Benchmark Report'),
    ]
    
    STATUS_CHOICES = [
        ('planning', 'Planning'),
        ('in_progress', 'In Progress'),
        ('completed', 'Completed'),
        ('published', 'Published'),
        ('archived', 'Archived'),
    ]
    
    # Project information
    title = models.CharField(max_length=255, help_text="Research project title")
    slug = models.SlugField(unique=True, help_text="URL-friendly identifier")
    description = models.TextField(help_text="Project description")
    research_type = models.CharField(
        max_length=50,
        choices=RESEARCH_TYPE_CHOICES,
        help_text="Type of research"
    )
    
    # Research details
    objective = models.TextField(help_text="Research objective and goals")
    methodology = models.TextField(help_text="Research methodology")
    sample_size = models.IntegerField(null=True, blank=True, help_text="Sample size for surveys")
    
    # Key findings
    key_findings = models.JSONField(
        default=list,
        help_text="Key findings from research"
    )
    
    # Status and timeline
    status = models.CharField(
        max_length=50,
        choices=STATUS_CHOICES,
        default='planning',
        help_text="Project status"
    )
    start_date = models.DateField(help_text="Project start date")
    completion_date = models.DateField(null=True, blank=True, help_text="Project completion date")
    publication_date = models.DateField(null=True, blank=True, help_text="Publication date")
    
    # Distribution
    published_url = models.URLField(blank=True, help_text="URL where research is published")
    media_mentions = models.IntegerField(default=0, help_text="Number of media mentions")
    backlinks_generated = models.IntegerField(default=0, help_text="Number of backlinks generated")
    
    # Tracking
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    
    class Meta:
        verbose_name = 'Research Project'
        verbose_name_plural = 'Research Projects'
        ordering = ['-publication_date', '-created_at']
    
    def __str__(self):
        return f"{self.title} ({self.get_research_type_display()})"
    
    def is_published(self) -> bool:
        """Check if research is published."""
        return self.status == 'published'
    
    def get_impact_score(self) -> float:
        """Calculate impact score based on mentions and backlinks."""
        return (self.media_mentions * 10) + (self.backlinks_generated * 5)


class MediaOutreach(models.Model):
    """Model for tracking media outreach and placements."""
    
    OUTREACH_TYPE_CHOICES = [
        ('publication', 'Publication'),
        ('podcast', 'Podcast'),
        ('speaking', 'Speaking Event'),
        ('interview', 'Interview'),
        ('guest_post', 'Guest Post'),
        ('webinar', 'Webinar'),
        ('conference', 'Conference'),
    ]
    
    STATUS_CHOICES = [
        ('pitch_sent', 'Pitch Sent'),
        ('in_discussion', 'In Discussion'),
        ('confirmed', 'Confirmed'),
        ('completed', 'Completed'),
        ('rejected', 'Rejected'),
        ('archived', 'Archived'),
    ]
    
    # Outreach information
    title = models.CharField(max_length=255, help_text="Outreach title")
    outreach_type = models.CharField(
        max_length=50,
        choices=OUTREACH_TYPE_CHOICES,
        help_text="Type of outreach"
    )
    
    # Target information
    target_publication = models.CharField(max_length=255, help_text="Target publication/platform")
    target_audience = models.CharField(max_length=255, help_text="Target audience")
    contact_name = models.CharField(max_length=255, blank=True, help_text="Contact person name")
    contact_email = models.EmailField(blank=True, help_text="Contact email")
    
    # Content details
    topic = models.CharField(max_length=255, help_text="Topic or subject")
    description = models.TextField(help_text="Outreach description")
    
    # Status and timeline
    status = models.CharField(
        max_length=50,
        choices=STATUS_CHOICES,
        default='pitch_sent',
        help_text="Outreach status"
    )
    pitch_date = models.DateField(help_text="Date pitch was sent")
    scheduled_date = models.DateField(null=True, blank=True, help_text="Scheduled date")
    completion_date = models.DateField(null=True, blank=True, help_text="Completion date")
    
    # Results
    result_url = models.URLField(blank=True, help_text="URL of published content")
    reach = models.IntegerField(default=0, help_text="Estimated reach/audience")
    engagement = models.IntegerField(default=0, help_text="Engagement metrics")
    backlinks_generated = models.IntegerField(default=0, help_text="Backlinks generated")
    
    # Tracking
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    
    class Meta:
        verbose_name = 'Media Outreach'
        verbose_name_plural = 'Media Outreach'
        ordering = ['-pitch_date']
    
    def __str__(self):
        return f"{self.title} - {self.target_publication}"
    
    def is_successful(self) -> bool:
        """Check if outreach was successful."""
        return self.status == 'completed'
    
    def get_roi_score(self) -> float:
        """Calculate ROI score based on reach and backlinks."""
        return (self.reach * 0.1) + (self.backlinks_generated * 10)


class AuthorProfile(ImageProcessingMixin, models.Model):
    """Model for author profiles and authority building."""
    
    # Author information
    name = models.CharField(max_length=255, help_text="Author name")
    slug = models.SlugField(unique=True, help_text="URL-friendly identifier")
    bio = models.TextField(help_text="Author biography")
    photo = models.ImageField(upload_to='author_photos/', blank=True, help_text="Author photo")
    
    # Image fields to process
    image_fields = ['photo']
    
    # Credentials and expertise
    title = models.CharField(max_length=255, help_text="Professional title")
    expertise_areas = models.JSONField(
        default=list,
        help_text="Areas of expertise"
    )
    certifications = models.JSONField(
        default=list,
        help_text="Professional certifications"
    )
    years_experience = models.IntegerField(help_text="Years of experience")
    
    # Social profiles
    website = models.URLField(blank=True, help_text="Personal website")
    linkedin_url = models.URLField(blank=True, help_text="LinkedIn profile URL")
    twitter_handle = models.CharField(max_length=100, blank=True, help_text="Twitter handle")
    github_url = models.URLField(blank=True, help_text="GitHub profile URL")
    
    # Content and authority
    articles_published = models.IntegerField(default=0, help_text="Number of articles published")
    speaking_engagements = models.IntegerField(default=0, help_text="Number of speaking engagements")
    media_mentions = models.IntegerField(default=0, help_text="Number of media mentions")
    
    # Authority metrics
    domain_authority = models.IntegerField(default=0, help_text="Personal domain authority")
    social_followers = models.IntegerField(default=0, help_text="Total social media followers")
    
    # Tracking
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    
    class Meta:
        verbose_name = 'Author Profile'
        verbose_name_plural = 'Author Profiles'
        ordering = ['name']
    
    def __str__(self):
        return self.name
    
    def get_authority_score(self) -> float:
        """Calculate author authority score."""
        return (
            (self.articles_published * 5) +
            (self.speaking_engagements * 10) +
            (self.media_mentions * 8) +
            (self.domain_authority * 2) +
            (self.social_followers * 0.01)
        )


# ============================================================================
# HOMEPAGE CONTENT MODELS - Dynamic Homepage Management
# ============================================================================

class HeroSection(ImageProcessingMixin, models.Model):
    """Model for managing the hero section of the homepage."""
    
    headline = models.CharField(
        max_length=255,
        help_text="Main headline (e.g., 'Comprehensive Facilities Management')"
    )
    subheading = models.CharField(
        max_length=255,
        help_text="Subheading text"
    )
    description = models.TextField(
        help_text="Hero section description"
    )
    badge_text = models.CharField(
        max_length=100,
        default="Trusted by 50+ Businesses",
        help_text="Badge text displayed in hero"
    )
    
    # Image fields to process
    image_fields = ['hero_image']
    # Optimized hero image specs (WebP)
    hero_image_small_webp = ImageSpecField(
        source='hero_image',
        processors=[ResizeToFit(800, 600)],
        format='WEBP',
        options={'quality': 85}
    )
    hero_image_medium_webp = ImageSpecField(
        source='hero_image',
        processors=[ResizeToFit(1200, 900)],
        format='WEBP',
        options={'quality': 88}
    )
    hero_image_webp = ImageSpecField(
        source='hero_image',
        processors=[ResizeToFit(1600, 1200)],
        format='WEBP',
        options={'quality': 90}
    )
    
    # CTA Buttons
    cta_primary_text = models.CharField(
        max_length=50,
        default="Get Free Consultation",
        help_text="Primary CTA button text"
    )
    cta_primary_url = models.CharField(
        max_length=255,
        default="/contact/",
        help_text="Primary CTA button URL"
    )
    cta_secondary_text = models.CharField(
        max_length=50,
        default="Explore Services",
        help_text="Secondary CTA button text"
    )
    cta_secondary_url = models.CharField(
        max_length=255,
        default="/services/",
        help_text="Secondary CTA button URL"
    )
    
    # Hero Image
    hero_image = models.ImageField(
        upload_to='hero/',
        help_text="Hero section background/featured image"
    )
    hero_image_alt = models.CharField(
        max_length=125,
        blank=True,
        help_text="Alt text for hero image (SEO)"
    )
    
    # Trust Indicators
    trust_indicator_1_label = models.CharField(
        max_length=100,
        default="Sites Covered",
        help_text="First trust indicator label"
    )
    trust_indicator_1_value = models.CharField(
        max_length=50,
        default="100",
        help_text="First trust indicator value"
    )
    
    trust_indicator_2_label = models.CharField(
        max_length=100,
        default="Years Experience",
        help_text="Second trust indicator label"
    )
    trust_indicator_2_value = models.CharField(
        max_length=50,
        default="6",
        help_text="Second trust indicator value"
    )
    
    trust_indicator_3_label = models.CharField(
        max_length=100,
        default="Support Available",
        help_text="Third trust indicator label"
    )
    trust_indicator_3_value = models.CharField(
        max_length=50,
        default="24",
        help_text="Third trust indicator value"
    )
    
    # Floating Card
    uptime_percentage = models.DecimalField(
        max_digits=5,
        decimal_places=1,
        default=99.8,
        help_text="Security uptime percentage"
    )
    
    # Badges
    licensed_badge_text = models.CharField(
        max_length=100,
        default="Licensed & Insured",
        help_text="Licensed badge text"
    )
    trust_badge_text = models.CharField(
        max_length=100,
        default="Trusted by 50+ businesses",
        help_text="Trust badge text"
    )
    
    # Status
    is_active = models.BooleanField(
        default=True,
        help_text="Display this hero section on homepage"
    )
    regions = models.ManyToManyField(
        Region,
        blank=True,
        related_name='hero_sections',
        help_text="Optional: limit this hero to selected regions (empty = global)"
    )
    
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    
    class Meta:
        verbose_name = "Hero Section"
        verbose_name_plural = "Hero Sections"
    
    def __str__(self):
        return f"Hero Section - {self.headline[:50]}"


class Certification(ImageProcessingMixin, models.Model):
    """Model for managing certifications displayed on homepage."""
    
    title = models.CharField(
        max_length=200,
        help_text="Certification title (e.g., 'Quality Management')"
    )
    description = models.CharField(
        max_length=255,
        help_text="Certification description (e.g., 'ISO 9001 Certified')"
    )
    image = models.ImageField(
        upload_to='certifications/',
        help_text="Certification logo/image"
    )
    image_alt = models.CharField(
        max_length=125,
        blank=True,
        help_text="Alt text for certification image (SEO)"
    )
    
    # Image fields to process
    image_fields = ['image']
    
    # Optimized image specs
    image_thumbnail = ImageSpecField(
        source='image',
        processors=[ResizeToFill(300, 300)],
        format='WEBP',
        options={'quality': 85}
    )
    
    image_webp = ImageSpecField(
        source='image',
        format='WEBP',
        options={'quality': 90}
    )
    order = models.PositiveIntegerField(
        default=0,
        help_text="Display order (lower numbers appear first)"
    )
    is_published = models.BooleanField(
        default=True,
        help_text="Display this certification on homepage"
    )
    regions = models.ManyToManyField(
        Region,
        blank=True,
        related_name='certifications',
        help_text="Optional: limit this certification to selected regions (empty = global)"
    )
    
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    
    class Meta:
        verbose_name = "Certification"
        verbose_name_plural = "Certifications"
        ordering = ['order']
    
    def __str__(self):
        return self.title


class CertificationSection(models.Model):
    """Model for managing the certifications section header."""
    
    badge_text = models.CharField(
        max_length=100,
        default="Industry Certified Excellence",
        help_text="Section badge text"
    )
    title = models.CharField(
        max_length=200,
        default="Our accreditations",
        help_text="Section title"
    )
    description = models.TextField(
        help_text="Section description"
    )
    
    # Trust indicators
    trust_indicator_1 = models.CharField(
        max_length=100,
        default="Verified Standards",
        help_text="First trust indicator"
    )
    trust_indicator_2 = models.CharField(
        max_length=100,
        default="Compliant Operations",
        help_text="Second trust indicator"
    )
    trust_indicator_3 = models.CharField(
        max_length=100,
        default="Industry Leading",
        help_text="Third trust indicator"
    )
    
    is_active = models.BooleanField(
        default=True,
        help_text="Display this section on homepage"
    )
    regions = models.ManyToManyField(
        Region,
        blank=True,
        related_name='certification_sections',
        help_text="Optional: limit this section to selected regions (empty = global)"
    )
    
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    
    class Meta:
        verbose_name = "Certification Section"
        verbose_name_plural = "Certification Sections"
    
    def __str__(self):
        return self.title


class WhyChooseSection(models.Model):
    """Model for managing the 'Why Choose Us' section."""
    
    title = models.CharField(
        max_length=200,
        default="Why Choose X Infinity Group",
        help_text="Section title"
    )
    description = models.TextField(
        help_text="Section description"
    )
    is_active = models.BooleanField(
        default=True,
        help_text="Display this section on homepage"
    )
    regions = models.ManyToManyField(
        Region,
        blank=True,
        related_name='why_choose_sections',
        help_text="Optional: limit this section to selected regions (empty = global)"
    )
    
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    
    class Meta:
        verbose_name = "Why Choose Section"
        verbose_name_plural = "Why Choose Sections"
    
    def __str__(self):
        return self.title


class FeatureCard(models.Model):
    """Model for feature cards in the 'Why Choose Us' section."""
    
    section = models.ForeignKey(
        WhyChooseSection,
        on_delete=models.CASCADE,
        related_name='feature_cards',
        help_text="Parent Why Choose section"
    )
    title = models.CharField(
        max_length=200,
        help_text="Feature card title"
    )
    description = models.TextField(
        help_text="Feature card description"
    )
    icon = models.CharField(
        max_length=50,
        help_text="Icon name (e.g., 'briefcase', 'users', 'zap')"
    )
    order = models.PositiveIntegerField(
        default=0,
        help_text="Display order"
    )
    
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    
    class Meta:
        verbose_name = "Feature Card"
        verbose_name_plural = "Feature Cards"
        ordering = ['order']
    
    def __str__(self):
        return f"{self.section.title} - {self.title}"


class KeyDifferentiator(models.Model):
    """Model for key differentiators in the 'Why Choose Us' section."""
    
    title = models.CharField(
        max_length=200,
        help_text="Differentiator title"
    )
    description = models.TextField(
        help_text="Differentiator description"
    )
    icon = models.CharField(
        max_length=50,
        help_text="Icon name (e.g., 'clock', 'shield', 'heart')"
    )
    order = models.PositiveIntegerField(
        default=0,
        help_text="Display order"
    )
    is_published = models.BooleanField(
        default=True,
        help_text="Display this differentiator"
    )
    regions = models.ManyToManyField(
        Region,
        blank=True,
        related_name='key_differentiators',
        help_text="Optional: limit this differentiator to selected regions (empty = global)"
    )
    
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    
    class Meta:
        verbose_name = "Key Differentiator"
        verbose_name_plural = "Key Differentiators"
        ordering = ['order']
    
    def __str__(self):
        return self.title


class TestimonialSection(models.Model):
    """Model for managing the testimonials section."""
    
    title = models.CharField(
        max_length=200,
        default="What Our Clients Say",
        help_text="Section title"
    )
    description = models.TextField(
        blank=True,
        help_text="Section description"
    )
    is_active = models.BooleanField(
        default=True,
        help_text="Display this section on homepage"
    )
    regions = models.ManyToManyField(
        Region,
        blank=True,
        related_name='testimonial_sections',
        help_text="Optional: limit this section to selected regions (empty = global)"
    )
    
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    
    class Meta:
        verbose_name = "Testimonial Section"
        verbose_name_plural = "Testimonial Sections"
    
    def __str__(self):
        return self.title


class SeoAdvance(models.Model):
    """Model for managing advanced SEO settings and configurations."""
    
    PRIORITY_CHOICES = [
        ('low', 'Low'),
        ('medium', 'Medium'),
        ('high', 'High'),
        ('critical', 'Critical'),
    ]
    
    STATUS_CHOICES = [
        ('pending', 'Pending'),
        ('in_progress', 'In Progress'),
        ('completed', 'Completed'),
        ('archived', 'Archived'),
    ]
    
    title = models.CharField(
        max_length=200,
        help_text="Title of the SEO task or configuration"
    )
    description = models.TextField(
        blank=True,
        help_text="Detailed description of the SEO task"
    )
    
    # SEO Configuration Fields
    target_keywords = models.TextField(
        blank=True,
        help_text="Target keywords (comma-separated)"
    )
    target_url = models.URLField(
        blank=True,
        help_text="Target URL for this SEO task"
    )
    canonical_url = models.URLField(
        blank=True,
        help_text="Canonical URL if different"
    )
    
    # Schema Markup
    schema_markup = models.TextField(
        blank=True,
        help_text="JSON-LD schema markup code"
    )
    
    # Meta Tags
    custom_meta_tags = models.TextField(
        blank=True,
        help_text="Custom meta tags (HTML format)"
    )
    
    # Robots Configuration
    robots_meta = models.CharField(
        max_length=200,
        blank=True,
        default="index, follow",
        help_text="Robots meta tag content (e.g., 'index, follow', 'noindex, nofollow')"
    )
    
    # Hreflang Tags
    hreflang_tags = models.TextField(
        blank=True,
        help_text="Hreflang tags for international SEO (one per line)"
    )
    
    # Open Graph & Twitter Cards
    og_title = models.CharField(
        max_length=200,
        blank=True,
        help_text="Open Graph title"
    )
    og_description = models.TextField(
        max_length=300,
        blank=True,
        help_text="Open Graph description"
    )
    og_image = models.ImageField(
        upload_to='seo/og_images/',
        blank=True,
        null=True,
        help_text="Open Graph image (1200x630px recommended)"
    )
    twitter_card_type = models.CharField(
        max_length=50,
        blank=True,
        default="summary_large_image",
        help_text="Twitter card type"
    )
    
    # Priority and Status
    priority = models.CharField(
        max_length=20,
        choices=PRIORITY_CHOICES,
        default='medium',
        help_text="Priority level for this SEO task"
    )
    status = models.CharField(
        max_length=20,
        choices=STATUS_CHOICES,
        default='pending',
        help_text="Current status of this SEO task"
    )
    
    # Analytics
    target_traffic = models.PositiveIntegerField(
        blank=True,
        null=True,
        help_text="Target monthly traffic goal"
    )
    current_ranking = models.PositiveIntegerField(
        blank=True,
        null=True,
        help_text="Current search ranking position"
    )
    target_ranking = models.PositiveIntegerField(
        blank=True,
        null=True,
        help_text="Target search ranking position"
    )
    
    # Notes and Implementation
    implementation_notes = models.TextField(
        blank=True,
        help_text="Implementation notes and instructions"
    )
    results_notes = models.TextField(
        blank=True,
        help_text="Results and observations after implementation"
    )
    
    # Regions
    regions = models.ManyToManyField(
        Region,
        blank=True,
        related_name='seo_advances',
        help_text="Regions this SEO task applies to (empty = all regions)"
    )
    
    # Publishing
    is_active = models.BooleanField(
        default=True,
        help_text="Is this SEO configuration active?"
    )
    
    # Timestamps
    due_date = models.DateField(
        blank=True,
        null=True,
        help_text="Due date for completion"
    )
    completed_date = models.DateField(
        blank=True,
        null=True,
        help_text="Date when task was completed"
    )
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    
    class Meta:
        verbose_name = "SEO Advance"
        verbose_name_plural = "SEO Advances"
        ordering = ['-priority', '-created_at']
        indexes = [
            models.Index(fields=['status', 'priority']),
            models.Index(fields=['is_active']),
            models.Index(fields=['created_at']),
        ]
    
    def __str__(self):
        return f"{self.title} ({self.get_status_display()})"
    
    def save(self, *args, **kwargs):
        # Auto-set completed_date when status changes to completed
        if self.status == 'completed' and not self.completed_date:
            from django.utils import timezone
            self.completed_date = timezone.now().date()
        super().save(*args, **kwargs)
