from django.db import models
from django.core.exceptions import ValidationError
from coresite.mixin import AbstractTimeStampModel
from django.contrib.auth import get_user_model
User = get_user_model()


class CompanyBotSettings(AbstractTimeStampModel):
    """Settings for company-specific bot configurations"""
    BOT_CHOICES = [
        ('hazel', 'Hazel'),
        ('maya', 'Maya'),
    ]
    company = models.ForeignKey('Company', on_delete=models.CASCADE, related_name='bot_settings')
    bot_name = models.CharField(max_length=50, choices=BOT_CHOICES)
    phone_number = models.CharField(max_length=20, null=True, blank=True, help_text="Phone number of the bot")
    is_active = models.BooleanField(default=True, help_text="Whether this bot setting is active")

class Holiday(AbstractTimeStampModel):
    """Holiday model for company-specific holidays"""
    company = models.ForeignKey('Company', on_delete=models.CASCADE, related_name='holidays')
    name = models.CharField(max_length=255, help_text="Holiday name (e.g., Christmas, EID)")
    message = models.TextField(null=True, blank=True, help_text="Holiday message")
    start_date = models.DateField(help_text="Start date of holiday period")
    end_date = models.DateField(help_text="End date of holiday period")
    is_active = models.BooleanField(default=True, help_text="Whether this holiday is active")
    bots = models.ManyToManyField(
        'CompanyBotSettings',
        blank=True,
        related_name='holidays',
        help_text="Bots this holiday applies to"
    )

    class Meta:
        unique_together = ['company', 'name', 'start_date']  # Prevent duplicate holidays
        ordering = ['start_date']
        verbose_name_plural = "Holidays"

    def __str__(self):
        if self.start_date == self.end_date:
            return f"{self.company.name} - {self.name} ({self.start_date})"
        return f"{self.company.name} - {self.name} ({self.start_date} to {self.end_date})"

    def clean(self):
        """Validate holiday dates"""
        super().clean()

        if self.start_date and self.end_date:
            if self.start_date > self.end_date:
                raise ValidationError("End date must be after or equal to start date")

    def save(self, *args, **kwargs):
        self.clean()
        super().save(*args, **kwargs)

    def get_duration_days(self):
        """Get number of days in holiday period"""
        if self.start_date and self.end_date:
            return (self.end_date - self.start_date).days + 1
        return 0


class OfficeHours(AbstractTimeStampModel):
    """Office hours configuration for each day of the week"""
    DAY_CHOICES = [
        ('monday', 'Monday'),
        ('tuesday', 'Tuesday'),
        ('wednesday', 'Wednesday'),
        ('thursday', 'Thursday'),
        ('friday', 'Friday'),
        ('saturday', 'Saturday'),
        ('sunday', 'Sunday'),
    ]
    
    company = models.ForeignKey('Company', on_delete=models.CASCADE, related_name='office_hours')
    day = models.CharField(max_length=10, choices=DAY_CHOICES)
    is_open = models.BooleanField(default=False, help_text="Whether the office is open on this day")
    start_time = models.TimeField(null=True, blank=True, help_text="Office opening time")
    end_time = models.TimeField(null=True, blank=True, help_text="Office closing time")
    
    class Meta:
        unique_together = ['company', 'day']
        ordering = ['day']
        verbose_name_plural = "Office Hours"
    
    def __str__(self):
        if self.is_open:
            return f"{self.company.name} - {self.get_day_display()}: {self.start_time} - {self.end_time}"
        return f"{self.company.name} - {self.get_day_display()}: Closed"
    
    def clean(self):
        """Validate office hours configuration"""
        super().clean()
        
        if self.is_open:
            if not self.start_time or not self.end_time:
                raise ValidationError("Start and end times are required when office is open")
            
            if self.start_time >= self.end_time:
                raise ValidationError("End time must be after start time")
    
    def save(self, *args, **kwargs):
        self.clean()
        super().save(*args, **kwargs)

class SalesTiming(AbstractTimeStampModel):
    """Sales timing configuration for bots"""
    BOT_CHOICES = [
        ('hazel', 'Hazel'),
    ]
    company = models.ForeignKey('Company', on_delete=models.CASCADE, related_name='sales_timings')
    start_time = models.TimeField(help_text="Sales start time")
    end_time = models.TimeField(help_text="Sales end time")
    is_active = models.BooleanField(default=True, help_text="Whether this sales timing is active")
    bot = models.CharField(max_length=100, choices=BOT_CHOICES, help_text="Bot this sales timing applies to")
    
    class Meta:
        verbose_name_plural = "Sales Timings"
        ordering = ['company', 'start_time']
    
    def __str__(self):
        return f"{self.company.name} - {self.bot}: {self.start_time} - {self.end_time}"
    
    def clean(self):
        """Validate sales timing configuration"""
        super().clean()
        
        if not self.start_time or not self.end_time:
            raise ValidationError("Start and end times are required")
        
        if self.start_time >= self.end_time:
            raise ValidationError("End time must be after start time")
    
    def save(self, *args, **kwargs):
        self.clean()
        super().save(*args, **kwargs)

class CatchPhrase(AbstractTimeStampModel):
    """Catchphrases for companies"""
    company = models.ForeignKey('Company', on_delete=models.CASCADE, related_name='catch_phrases')
    phrase = models.CharField(max_length=255, help_text="Short catch phrase")
    
    class Meta:
        verbose_name_plural = "Catch Phrases"
        ordering = ['company', 'phrase']
    
    def __str__(self):
        return f"{self.company.name} - {self.phrase}"
    
    def clean(self):
        """Validate catchphrase"""
        super().clean()
        
        if not self.phrase or not self.phrase.strip():
            raise ValidationError("Catch phrase cannot be empty")
    
    def save(self, *args, **kwargs):
        self.clean()
        super().save(*args, **kwargs)

class CompanyHistory(AbstractTimeStampModel):
    """History tracking for all company-related changes"""
    company = models.ForeignKey('Company', on_delete=models.CASCADE, related_name='history')
    updated_by = models.ForeignKey('core.User', on_delete=models.CASCADE, related_name='company_actions')
    action = models.CharField(max_length=50, help_text="Action performed: created, updated, deleted")
    model_name = models.CharField(max_length=100, help_text="Name of the model that was changed")
    object_id = models.IntegerField(null=True, blank=True, help_text="ID of the changed object")
    details = models.TextField(help_text="Human readable description of what changed", null=True, blank=True)
    
    class Meta:
        verbose_name_plural = "Company History"
        ordering = ['-created_at']  # Most recent first
    
    def __str__(self):
        return f"{self.company.name} - {self.action} {self.model_name} (ID: {self.object_id}) by {self.updated_by.username}"

class Company(AbstractTimeStampModel):
    """Company model for multi-tenancy"""
    name = models.CharField(max_length=255)
    phone = models.CharField(max_length=50, blank=True, null=True)
    office_time = models.TextField(blank=True, null=True)
    bdc_number = models.CharField(max_length=50, blank=True, null=True)
    timezone = models.CharField(max_length=50, default='UTC')
    missing_call_notify_to = models.ManyToManyField(
        User,
        blank=True,
        related_name='missing_call_notify_companies',
        help_text="Users who will be notified when calls are missed"
    )
    default_transfer_staff = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='default_transfer_companies',
        help_text="Default user to receive calls when no other agents are available"
    )
    website = models.TextField(blank=True, null=True)
    bio = models.TextField(blank=True, null=True)

    is_active = models.BooleanField(default=True)

    def __str__(self):
        return self.name
    
    def get_user_count(self):
        """Get the number of users in this company"""
        return self.users.count()
    
    def get_active_users(self):
        """Get all active users in this company"""
        return self.users.filter(is_active=True)

    def get_all_users(self):
        """Get all active users in this company"""
        return self.users.filter()

    def get_default_transfer_staff_name(self):
        """Get the name of default transfer staff"""
        if self.default_transfer_staff:
            return self.default_transfer_staff.username
        return "Not Set"
    
    def get_office_hours_for_day(self, day_name):
        """Get office hours for a specific day"""
        try:
            return self.office_hours.get(day=day_name.lower())
        except OfficeHours.DoesNotExist:
            return None
    
    def get_office_hours_summary(self):
        """Get a summary of office hours for display"""
        summary = []
        
        for day in ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday']:
            hours = self.get_office_hours_for_day(day)
            if hours and hours.is_open:
                summary.append(f"{hours.get_day_display()}: {hours.start_time} - {hours.end_time}")
            else:
                # Handle case where no office hours exist for this day
                day_display = day.title()  # Capitalize first letter
                summary.append(f"{day_display}: Closed")
        
        return summary
    
    def get_active_sales_timings(self):
        """Get all active sales timings for this company"""
        return self.sales_timings.filter(is_active=True)
    
    def get_sales_timings_summary(self):
        """Get a summary of sales timings for display"""
        summary = []
        for timing in self.get_active_sales_timings():
            summary.append(f"{timing.bot}: {timing.start_time} - {timing.end_time}")
        return summary if summary else ["No active sales timings"]
    
    def get_catch_phrases_list(self):
        """Get list of all catchphrases for this company"""
        return list(self.catch_phrases.values_list('phrase', flat=True))
    
    def get_catch_phrases_summary(self):
        """Get a summary of catchphrases for display"""
        phrases = self.get_catch_phrases_list()
        return phrases if phrases else ["No catch phrases set"]

    class Meta:
        verbose_name_plural = "Companies"

class Dealership(AbstractTimeStampModel):
    company = models.ForeignKey(Company, on_delete=models.CASCADE, related_name="dealerships")
    name = models.CharField(max_length=255)
    contact_person_name = models.CharField(max_length=255)
    contact_phone = models.CharField(max_length=50, unique=True)

    class Meta:
        unique_together = ('company', 'name')

    def __str__(self):
        return self.name + ' - ' + self.company.name
