from django.db import models
from django.contrib.auth.models import User, Group
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.utils.translation import gettext_lazy as _
from django.utils.translation import get_language
from django.utils import timezone
from django.core.files import File
import random
import string
import os
from io import BytesIO
from PIL import Image

class Country(models.Model):
    name = models.CharField(_('Country Name'), max_length=100)
    code = models.CharField(_('Country Code'), max_length=10)
    is_default = models.BooleanField(_('Is Default'), default=False)

    class Meta:
        verbose_name = _('Country')
        verbose_name_plural = _('Countries')

    def __str__(self):
        return f"{self.name} (+{self.code})"

class City(models.Model):
    country = models.ForeignKey(Country, on_delete=models.CASCADE, related_name='cities')
    name = models.CharField(_('City Name'), max_length=100)

    class Meta:
        verbose_name = _('City')
        verbose_name_plural = _('Cities')
        ordering = ['name']

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

class TruckType(models.Model):
    name = models.CharField(_('Name (EN)'), max_length=100)
    name_ar = models.CharField(_('Name (AR)'), max_length=100, blank=True)

    class Meta:
        verbose_name = _('Truck Type')
        verbose_name_plural = _('Truck Types')

    def __str__(self):
        if get_language() == 'ar' and self.name_ar:
            return self.name_ar
        return self.name

class Profile(models.Model):
    ROLE_CHOICES = (
        ('SHIPPER', _('Shipper (Need Goods Moved)')),
        ('TRUCK_OWNER', _('Truck Owner (Service Provider)')),
        ('ADMIN', _('Administrator')),
    )
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    role = models.CharField(max_length=20, choices=ROLE_CHOICES, default='SHIPPER')
    SUBSCRIPTION_CHOICES = (
        ('MONTHLY', _('Monthly')),
        ('ANNUAL', _('Annual')),
        ('NONE', _('None')),
    )
    subscription_plan = models.CharField(max_length=20, choices=SUBSCRIPTION_CHOICES, default='NONE')
    subscription_expiry = models.DateField(null=True, blank=True)
    is_subscription_active = models.BooleanField(default=False)
    
    # New Profile Picture field
    profile_picture = models.ImageField(_('Profile Picture'), upload_to='profiles/', blank=True, null=True)
    email_verified = models.BooleanField(default=False)
    phone_verified = models.BooleanField(default=False)

    def is_expired(self):
        if self.subscription_plan == "NONE":
            return False
        if not self.is_subscription_active:
            return True
        if not self.subscription_expiry:
            return True
        return self.subscription_expiry < timezone.now().date()

    country_code = models.CharField(max_length=5, blank=True, default="966")
    phone_number = models.CharField(max_length=20, unique=True, null=True) # Changed to unique and nullable for migration safety
    
    @property
    def full_phone_number(self):
        if not self.phone_number:
            return ""
        # Remove any existing leading + from country code and phone number
        cc = str(self.country_code).replace("+", "").strip()
        pn = str(self.phone_number).replace("+", "").strip()
        return f"{cc}{pn}"

    def __str__(self):
        return f"{self.user.username} - {self.role}"
    
    def save(self, *args, **kwargs):
        if self.profile_picture:
            self.profile_picture = self.compress_image(self.profile_picture)
        super().save(*args, **kwargs)

    def compress_image(self, image_field):
        if not image_field:
            return image_field
        
        try:
            # Check file extension
            ext = os.path.splitext(image_field.name)[1].lower()
            if ext not in ['.jpg', '.jpeg', '.png', '.webp']:
                return image_field

            img = Image.open(image_field)
            
            if img.mode != 'RGB':
                img = img.convert('RGB')
            
            # Resize if too large
            max_size = (500, 500)
            img.thumbnail(max_size, Image.LANCZOS)
            
            output = BytesIO()
            img.save(output, format='JPEG', quality=80, optimize=True)
            output.seek(0)
            
            new_name = os.path.splitext(image_field.name)[0] + '.jpg'
            return File(output, name=new_name)
        except Exception as e:
            # Not an image or other error, return as is
            return image_field

class OTPCode(models.Model):
    phone_number = models.CharField(max_length=20, null=True, blank=True)
    email = models.EmailField(null=True, blank=True)
    code = models.CharField(max_length=6)
    created_at = models.DateTimeField(auto_now_add=True)
    is_used = models.BooleanField(default=False)

    def is_valid(self):
        # Valid for 10 minutes
        return not self.is_used and (timezone.now() - self.created_at).total_seconds() < 600

    @staticmethod
    def generate_code(phone_number=None, email=None):
        code = ''.join(random.choices(string.digits, k=6))
        return OTPCode.objects.create(phone_number=phone_number, email=email, code=code)

class Truck(models.Model):
    owner = models.ForeignKey(User, on_delete=models.CASCADE, related_name='trucks')
    
    # Using a fresh name to avoid conflict with partially created fields
    truck_type_link = models.ForeignKey(TruckType, on_delete=models.SET_NULL, null=True, blank=True, verbose_name=_('Truck Type (New)'))
    
    # English fields
    truck_type = models.CharField(_('Truck Type (EN)'), max_length=100, blank=True)
    model = models.CharField(_('Model (EN)'), max_length=100)
    load_capacity = models.CharField(_('Load Capacity (EN)'), max_length=100)
    color = models.CharField(_('Color (EN)'), max_length=50)

    # Arabic fields
    truck_type_ar = models.CharField(_('Truck Type (AR)'), max_length=100, blank=True)
    model_ar = models.CharField(_('Model (AR)'), max_length=100, blank=True)
    load_capacity_ar = models.CharField(_('Load Capacity (AR)'), max_length=100, blank=True)
    color_ar = models.CharField(_('Color (AR)'), max_length=50, blank=True)

    year = models.PositiveIntegerField(_('Year'))
    plate_no = models.CharField(_('Plate No'), max_length=50)
    registration_expiry_date = models.DateField(_('Registration Expiry Date'), null=True, blank=True)
    
    # Pictures
    truck_picture = models.ImageField(_('Truck Picture'), upload_to='trucks/', blank=True, null=True)
    registration_front = models.FileField(_('Registration (Front Face)'), upload_to='docs/', blank=True, null=True)
    registration_back = models.FileField(_('Registration (Back Face)'), upload_to='docs/', blank=True, null=True)
    driver_license_front = models.FileField(_('Driver License (Front Face)'), upload_to='docs/', blank=True, null=True)
    driver_license_back = models.FileField(_('Driver License (Back Face)'), upload_to='docs/', blank=True, null=True)

    is_approved = models.BooleanField(_('Is Approved'), default=False)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        if self.truck_type_link:
            return f"{self.truck_type_link} - {self.plate_no}"
        return f"{self.truck_type} - {self.plate_no}"

    @property
    def display_truck_type(self):
        if self.truck_type_link:
            return str(self.truck_type_link)
        if get_language() == 'ar' and self.truck_type_ar:
            return self.truck_type_ar
        return self.truck_type

    @property
    def display_model(self):
        if get_language() == 'ar' and self.model_ar:
            return self.model_ar
        return self.model

    @property
    def display_load_capacity(self):
        if get_language() == 'ar' and self.load_capacity_ar:
            return self.load_capacity_ar
        return self.load_capacity

    @property
    def display_color(self):
        if get_language() == 'ar' and self.color_ar:
            return self.color_ar
        return self.color

    def save(self, *args, **kwargs):
        # Compress images
        if self.truck_picture:
            self.truck_picture = self.compress_image(self.truck_picture)
        
        # For docs, compress only if they are images
        if self.registration_front:
            self.registration_front = self.compress_image(self.registration_front)
        if self.registration_back:
            self.registration_back = self.compress_image(self.registration_back)
        if self.driver_license_front:
            self.driver_license_front = self.compress_image(self.driver_license_front)
        if self.driver_license_back:
            self.driver_license_back = self.compress_image(self.driver_license_back)
            
        super().save(*args, **kwargs)

    def compress_image(self, image_field):
        if not image_field:
            return image_field
        
        try:
            # Check file extension
            ext = os.path.splitext(image_field.name)[1].lower()
            if ext not in ['.jpg', '.jpeg', '.png', '.webp']:
                return image_field

            img = Image.open(image_field)
            
            # If already small enough, don't compress (optional, but good for performance)
            # if image_field.size < 300 * 1024: return image_field
            
            if img.mode != 'RGB':
                img = img.convert('RGB')
            
            # Resize if too large
            max_size = (1200, 1200)
            img.thumbnail(max_size, Image.LANCZOS)
            
            output = BytesIO()
            img.save(output, format='JPEG', quality=70, optimize=True)
            output.seek(0)
            
            new_name = os.path.splitext(image_field.name)[0] + '.jpg'
            return File(output, name=new_name)
        except Exception as e:
            # Not an image or other error, return as is
            return image_field

class Shipment(models.Model):
    STATUS_CHOICES = (
        ('OPEN', _('Open for Bids')),
        ('IN_PROGRESS', _('In Progress')),
        ('COMPLETED', _('Completed')),
        ('CANCELLED', _('Cancelled')),
    )
    shipper = models.ForeignKey(User, on_delete=models.CASCADE, related_name='shipments')
    description = models.TextField(_('Goods Description'))
    weight = models.CharField(_('Weight/Volume'), max_length=100)
    
    # Using a fresh name
    required_truck_type_link = models.ForeignKey(TruckType, on_delete=models.SET_NULL, null=True, blank=True, verbose_name=_('Required Truck Type'))
    
    origin_country = models.ForeignKey(Country, on_delete=models.SET_NULL, null=True, related_name='shipments_origin')
    origin_city = models.ForeignKey(City, on_delete=models.SET_NULL, null=True, related_name='shipments_origin')
    destination_country = models.ForeignKey(Country, on_delete=models.SET_NULL, null=True, related_name='shipments_destination')
    destination_city = models.ForeignKey(City, on_delete=models.SET_NULL, null=True, related_name='shipments_destination')
    
    origin = models.CharField(_('Origin (Legacy)'), max_length=255, blank=True)
    destination = models.CharField(_('Destination (Legacy)'), max_length=255, blank=True)
    
    delivery_date = models.DateField(_('Requested Delivery Date'))
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='OPEN')
    
    assigned_truck = models.ForeignKey(Truck, on_delete=models.SET_NULL, null=True, blank=True, related_name='assigned_shipments')
    
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"{self.display_origin} to {self.display_destination} - {self.status}"

    @property
    def display_origin(self):
        if self.origin_city and self.origin_country:
            return f"{self.origin_city.name}, {self.origin_country.name}"
        return self.origin

    @property
    def display_destination(self):
        if self.destination_city and self.destination_country:
            return f"{self.destination_city.name}, {self.destination_country.name}"
        return self.destination

class Bid(models.Model):
    STATUS_CHOICES = (
        ('PENDING', _('Pending')),
        ('ACCEPTED', _('Accepted')),
        ('REJECTED', _('Rejected')),
    )
    shipment = models.ForeignKey(Shipment, on_delete=models.CASCADE, related_name='bids')
    truck_owner = models.ForeignKey(User, on_delete=models.CASCADE, related_name='bids')
    truck = models.ForeignKey(Truck, on_delete=models.CASCADE)
    amount = models.DecimalField(_('Offer Amount'), max_digits=10, decimal_places=2)
    comments = models.TextField(_('Comments'), blank=True)
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='PENDING')
    
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"Bid by {self.truck_owner.username} for {self.shipment}"

class Message(models.Model):
    shipment = models.ForeignKey(Shipment, on_delete=models.CASCADE, related_name='messages')
    sender = models.ForeignKey(User, on_delete=models.CASCADE, related_name='sent_messages')
    content = models.TextField()
    timestamp = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"From {self.sender.username} at {self.timestamp}"

class WhatsAppConfig(models.Model):
    api_token = models.CharField(_('Wablas API Token'), max_length=255)
    secret_key = models.CharField(_('Wablas Secret Key'), max_length=255, blank=True, null=True)
    is_active = models.BooleanField(_('Is Active'), default=True)
    admin_phone = models.CharField(_("Admin Notification Phone"), max_length=20, blank=True, null=True, help_text=_("WhatsApp number to receive admin notifications (with country code, e.g., 96812345678)"))

    class Meta:
        verbose_name = _('WhatsApp Configuration')
        verbose_name_plural = _('WhatsApp Configuration')

    def __str__(self):
        return str(_("WhatsApp Configuration"))

class AppSetting(models.Model):
    app_name = models.CharField(_('App Name'), max_length=100)
    logo = models.ImageField(_('Logo'), upload_to='app/', blank=True, null=True)
    slogan = models.CharField(_('Slogan'), max_length=255, blank=True)
    registration_number = models.CharField(_('Registration Number'), max_length=100, blank=True)
    tax_number = models.CharField(_('Tax Number'), max_length=100, blank=True)
    contact_phone = models.CharField(_('Contact Phone'), max_length=20, blank=True)
    contact_email = models.EmailField(_('Contact Email'), blank=True)
    contact_address = models.TextField(_('Contact Address'), blank=True)
    terms_of_service = models.TextField(_('Terms of Service'), blank=True)
    privacy_policy = models.TextField(_('Privacy Policy'), blank=True)
    subscription_enabled = models.BooleanField(_('Enable Subscription Fee'), default=False)
    thawani_enabled = models.BooleanField(_("Enable Thawani Payment"), default=True)
    
    # Shipper Fees
    shipper_monthly_fee = models.DecimalField(_('Shipper Monthly Fee'), max_digits=10, decimal_places=2, default=0.00)
    shipper_annual_fee = models.DecimalField(_('Shipper Annual Fee'), max_digits=10, decimal_places=2, default=0.00)
    
    # Truck Owner Fees
    truck_owner_monthly_fee = models.DecimalField(_('Truck Owner Monthly Fee'), max_digits=10, decimal_places=2, default=0.00)
    truck_owner_annual_fee = models.DecimalField(_('Truck Owner Annual Fee'), max_digits=10, decimal_places=2, default=0.00)

    class Meta:
        verbose_name = _('App Setting')
        verbose_name_plural = _('App Settings')

    def __str__(self):
        return self.app_name

class Banner(models.Model):
    title = models.CharField(_('Title (EN)'), max_length=200)
    title_ar = models.CharField(_('Title (AR)'), max_length=200, blank=True)
    subtitle = models.CharField(_('Subtitle (EN)'), max_length=255, blank=True)
    subtitle_ar = models.CharField(_('Subtitle (AR)'), max_length=255, blank=True)
    image = models.ImageField(_('Banner Image'), upload_to='banners/')
    link = models.URLField(_('Link URL'), blank=True, null=True, help_text=_("Internal or external URL"))
    is_active = models.BooleanField(_('Is Active'), default=True)
    order = models.PositiveIntegerField(_('Order'), default=0)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        verbose_name = _('Banner')
        verbose_name_plural = _('Banners')
        ordering = ['order', '-created_at']

    def __str__(self):
        return self.title

    @property
    def display_title(self):
        if get_language() == 'ar' and self.title_ar:
            return self.title_ar
        return self.title

    @property
    def display_subtitle(self):
        if get_language() == 'ar' and self.subtitle_ar:
            return self.subtitle_ar
        return self.subtitle

class HomeSection(models.Model):
    SECTION_TYPES = (
        ('SIMPLE', _('Simple Text & Image')),
        ('FEATURES', _('Features List')),
        ('CTA', _('Call to Action')),
    )
    title = models.CharField(_('Title (EN)'), max_length=200)
    title_ar = models.CharField(_('Title (AR)'), max_length=200, blank=True)
    subtitle = models.CharField(_('Subtitle (EN)'), max_length=255, blank=True)
    subtitle_ar = models.CharField(_('Subtitle (AR)'), max_length=255, blank=True)
    content = models.TextField(_('Content (EN)'), blank=True)
    content_ar = models.TextField(_('Content (AR)'), blank=True)
    image = models.ImageField(_('Image'), upload_to='home_sections/', blank=True, null=True)
    order = models.PositiveIntegerField(_('Order'), default=0)
    is_active = models.BooleanField(_('Is Active'), default=True)
    section_type = models.CharField(max_length=20, choices=SECTION_TYPES, default='SIMPLE')
    background_color = models.CharField(max_length=50, default='white', help_text="e.g. white, light, primary")

    class Meta:
        verbose_name = _('Home Section')
        verbose_name_plural = _('Home Sections')
        ordering = ['order']

    def __str__(self):
        return self.title

    @property
    def display_title(self):
        if get_language() == 'ar' and self.title_ar:
            return self.title_ar
        return self.title

    @property
    def display_subtitle(self):
        if get_language() == 'ar' and self.subtitle_ar:
            return self.subtitle_ar
        return self.subtitle

    @property
    def display_content(self):
        if get_language() == 'ar' and self.content_ar:
            return self.content_ar
        return self.content

@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    if created:
        Profile.objects.create(user=instance)

@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
    if hasattr(instance, 'profile'):
        instance.profile.save()
    else:
        Profile.objects.create(user=instance)

@receiver(post_save, sender=Profile)
def sync_user_groups(sender, instance, **kwargs):
    """
    Automatically syncs Django Groups based on the Profile role.
    """
    # Get or create the group for the current role
    group, created = Group.objects.get_or_create(name=instance.role)
    
    # Get all possible role-based groups to clean up
    all_role_names = [role[0] for role in Profile.ROLE_CHOICES]
    
    # Remove user from other role groups they might be in
    other_groups = Group.objects.filter(name__in=all_role_names).exclude(name=instance.role)
    instance.user.groups.remove(*other_groups)
    
    # Add user to the correct group
    instance.user.groups.add(group)
class Transaction(models.Model):
    TRANSACTION_TYPES = (
        ('PAYMENT', _('Payment')),
        ('REFUND', _('Refund')),
    )
    STATUS_CHOICES = (
        ('PENDING', _('Pending')),
        ('COMPLETED', _('Completed')),
        ('FAILED', _('Failed')),
        ('CANCELLED', _('Cancelled')),
    )
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='transactions')
    amount = models.DecimalField(_('Amount'), max_digits=10, decimal_places=2)
    transaction_type = models.CharField(max_length=20, choices=TRANSACTION_TYPES, default='PAYMENT')
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='COMPLETED')
    description = models.TextField(_('Description'), blank=True)
    payment_method = models.CharField(_('Payment Method'), max_length=100, blank=True)
    reference_number = models.CharField(_('Reference Number'), max_length=100, blank=True)
    receipt_number = models.CharField(_('Receipt Number'), max_length=20, unique=True, blank=True)
    session_id = models.CharField(_("Session ID"), max_length=255, blank=True, null=True)
    payment_status = models.CharField(_("Payment Status"), max_length=50, blank=True, null=True)
    
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        verbose_name = _('Transaction')
        verbose_name_plural = _('Transactions')
        ordering = ['-created_at']

    def save(self, *args, **kwargs):
        if not self.receipt_number:
            # Generate a unique receipt number: REC-YYYYMMDD-XXXX
            date_str = timezone.now().strftime('%Y%m%d')
            random_str = ''.join(random.choices(string.ascii_uppercase + string.digits, k=4))
            self.receipt_number = f"REC-{date_str}-{random_str}"
        super().save(*args, **kwargs)

    def __str__(self):
        return f"{self.receipt_number} - {self.user.username} ({self.amount})"

class ContactMessage(models.Model):
    name = models.CharField(_('Name'), max_length=100)
    email = models.EmailField(_('Email'))
    subject = models.CharField(_('Subject'), max_length=200)
    message = models.TextField(_('Message'))
    created_at = models.DateTimeField(auto_now_add=True)
    is_read = models.BooleanField(default=False)

    class Meta:
        verbose_name = _('Contact Message')
        verbose_name_plural = _('Contact Messages')
        ordering = ['-created_at']

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

class Testimonial(models.Model):
    name = models.CharField(_('Customer Name (EN)'), max_length=100)
    name_ar = models.CharField(_('Customer Name (AR)'), max_length=100, blank=True)
    role = models.CharField(_('Customer Role (EN)'), max_length=100, blank=True)
    role_ar = models.CharField(_('Customer Role (AR)'), max_length=100, blank=True)
    content = models.TextField(_('Testimony (EN)'))
    content_ar = models.TextField(_('Testimony (AR)'), blank=True)
    rating = models.PositiveIntegerField(_('Rating (1-5)'), default=5)
    image = models.ImageField(_('Customer Image'), upload_to='testimonials/', blank=True, null=True)
    is_active = models.BooleanField(_('Is Active'), default=True)
    order = models.PositiveIntegerField(_('Order'), default=0)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        verbose_name = _('Testimonial')
        verbose_name_plural = _('Testimonials')
        ordering = ['order', '-created_at']

    def __str__(self):
        return self.name

    @property
    def display_name(self):
        if get_language() == 'ar' and self.name_ar:
            return self.name_ar
        return self.name

    @property
    def display_role(self):
        if get_language() == 'ar' and self.role_ar:
            return self.role_ar
        return self.role

    @property
    def display_content(self):
        if get_language() == 'ar' and self.content_ar:
            return self.content_ar
        return self.content
