from django.db import models
from django.utils.translation import gettext_lazy as _
from django.utils import timezone
from smoothschedule.identity.core.models import Tenant
from smoothschedule.identity.users.models import User


class Ticket(models.Model):
    """
    Represents a support ticket in the system.

    Ticket Types:
    - PLATFORM: Business Owner -> Platform Support (billing, technical issues with platform)
    - CUSTOMER: Customer -> Business (appointment issues, service inquiries)
    - STAFF_REQUEST: Staff -> Business Owner/Manager (time off, schedule changes)
    - INTERNAL: Business internal tickets (equipment issues, facilities)
    """

    class TicketType(models.TextChoices):
        PLATFORM = 'PLATFORM', _('Platform Support')
        CUSTOMER = 'CUSTOMER', _('Customer Inquiry')
        STAFF_REQUEST = 'STAFF_REQUEST', _('Staff Request')
        INTERNAL = 'INTERNAL', _('Internal Business Ticket')

    class Status(models.TextChoices):
        OPEN = 'OPEN', _('Open')
        IN_PROGRESS = 'IN_PROGRESS', _('In Progress')
        AWAITING_RESPONSE = 'AWAITING_RESPONSE', _('Awaiting Response')
        RESOLVED = 'RESOLVED', _('Resolved')
        CLOSED = 'CLOSED', _('Closed')

    class Priority(models.TextChoices):
        LOW = 'LOW', _('Low')
        MEDIUM = 'MEDIUM', _('Medium')
        HIGH = 'HIGH', _('High')
        URGENT = 'URGENT', _('Urgent')

    class Category(models.TextChoices):
        # Platform ticket categories
        BILLING = 'BILLING', _('Billing & Payments')
        TECHNICAL = 'TECHNICAL', _('Technical Issue')
        FEATURE_REQUEST = 'FEATURE_REQUEST', _('Feature Request')
        ACCOUNT = 'ACCOUNT', _('Account & Settings')
        # Customer/Business ticket categories
        APPOINTMENT = 'APPOINTMENT', _('Appointment Issue')
        REFUND = 'REFUND', _('Refund Request')
        COMPLAINT = 'COMPLAINT', _('Complaint')
        GENERAL_INQUIRY = 'GENERAL_INQUIRY', _('General Inquiry')
        # Staff request categories
        TIME_OFF = 'TIME_OFF', _('Time Off Request')
        SCHEDULE_CHANGE = 'SCHEDULE_CHANGE', _('Schedule Change')
        EQUIPMENT = 'EQUIPMENT', _('Equipment Issue')
        # General
        OTHER = 'OTHER', _('Other')

    tenant = models.ForeignKey(
        Tenant,
        on_delete=models.CASCADE,
        related_name='tickets',
        null=True, # For platform-level tickets created by platform admins, tenant might be null
        blank=True, # For platform-level tickets created by platform admins, tenant might be null
        help_text="The tenant (business) this ticket belongs to. Null for platform-level tickets."
    )
    is_sandbox = models.BooleanField(
        default=False,
        help_text="True for sandbox/test mode tickets - isolated from live data"
    )
    creator = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        related_name='created_tickets',
        null=True,
        help_text="The user who created this ticket."
    )
    assignee = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        related_name='assigned_tickets',
        null=True,
        blank=True,
        help_text="The user (e.g., support agent, staff) currently assigned to this ticket."
    )

    ticket_type = models.CharField(
        max_length=20,
        choices=TicketType.choices,
        default=TicketType.CUSTOMER,
        help_text="Distinguishes between platform support tickets and customer/staff tickets."
    )
    
    status = models.CharField(
        max_length=20,
        choices=Status.choices,
        default=Status.OPEN,
        help_text="Current status of the ticket."
    )
    
    priority = models.CharField(
        max_length=20,
        choices=Priority.choices,
        default=Priority.MEDIUM,
        help_text="Priority level of the ticket."
    )

    subject = models.CharField(max_length=255, help_text="Subject line of the ticket.")
    description = models.TextField(help_text="Detailed description of the issue or request.")
    
    category = models.CharField(
        max_length=50,
        choices=Category.choices,
        default=Category.OTHER,
        help_text="Category of the ticket."
    )

    # Related appointment for customer tickets (stored as ID string since Event is tenant-scoped)
    related_appointment_id = models.CharField(
        max_length=50,
        blank=True,
        null=True,
        help_text="ID of the related appointment for customer inquiry tickets."
    )

    # External email sender (for tickets created from email by non-users)
    external_email = models.EmailField(
        blank=True,
        null=True,
        help_text="Email address of external sender (when creator is not a registered user)."
    )
    external_name = models.CharField(
        max_length=255,
        blank=True,
        default='',
        help_text="Display name of external sender."
    )

    # Email address tracking
    source_email_address = models.ForeignKey(
        'TicketEmailAddress',
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='tickets',
        help_text="Email address this ticket was received from or sent to"
    )

    # SLA tracking
    due_at = models.DateTimeField(
        null=True,
        blank=True,
        help_text="SLA deadline based on priority."
    )
    first_response_at = models.DateTimeField(
        null=True,
        blank=True,
        help_text="When the first response was made."
    )

    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    resolved_at = models.DateTimeField(null=True, blank=True)

    class Meta:
        app_label = 'tickets'
        ordering = ['-priority', '-created_at']
        indexes = [
            models.Index(fields=['tenant', 'status']),
            models.Index(fields=['assignee', 'status']),
            models.Index(fields=['ticket_type', 'status']),
            models.Index(fields=['creator', 'status']),
            models.Index(fields=['category']),
        ]

    def __str__(self):
        return f"Ticket #{self.id}: {self.subject} ({self.get_status_display()})"

    def save(self, *args, **kwargs):
        # Set SLA due date based on priority if not already set
        if not self.due_at and not self.pk:
            self.due_at = self._calculate_sla_due_date()
        # Auto-set resolved_at when status changes to RESOLVED or CLOSED
        if self.status in [self.Status.RESOLVED, self.Status.CLOSED] and not self.resolved_at:
            self.resolved_at = timezone.now()
        elif self.status not in [self.Status.RESOLVED, self.Status.CLOSED]:
            self.resolved_at = None
        super().save(*args, **kwargs)

    def _calculate_sla_due_date(self):
        """Calculate SLA due date based on priority."""
        from datetime import timedelta
        now = timezone.now()
        sla_hours = {
            self.Priority.URGENT: 1,
            self.Priority.HIGH: 4,
            self.Priority.MEDIUM: 24,
            self.Priority.LOW: 72,
        }
        hours = sla_hours.get(self.priority, 24)
        return now + timedelta(hours=hours)

    @property
    def is_overdue(self):
        """Check if ticket is past SLA deadline."""
        if not self.due_at:
            return False
        if self.status in [self.Status.RESOLVED, self.Status.CLOSED]:
            return False
        return timezone.now() > self.due_at


class TicketTemplate(models.Model):
    """
    Predefined templates for common ticket types.
    Can be platform-wide or tenant-specific.
    """
    tenant = models.ForeignKey(
        Tenant,
        on_delete=models.CASCADE,
        related_name='ticket_templates',
        null=True,
        blank=True,
        help_text="Tenant this template belongs to. Null for platform-wide templates."
    )
    name = models.CharField(max_length=100, help_text="Template name.")
    description = models.TextField(blank=True, help_text="Description of when to use this template.")
    ticket_type = models.CharField(
        max_length=20,
        choices=Ticket.TicketType.choices,
        help_text="Type of ticket this template creates."
    )
    category = models.CharField(
        max_length=50,
        choices=Ticket.Category.choices,
        default=Ticket.Category.OTHER,
    )
    default_priority = models.CharField(
        max_length=20,
        choices=Ticket.Priority.choices,
        default=Ticket.Priority.MEDIUM,
    )
    subject_template = models.CharField(
        max_length=255,
        help_text="Default subject line. Can include placeholders like {customer_name}."
    )
    description_template = models.TextField(
        help_text="Default description. Can include placeholders."
    )
    is_active = models.BooleanField(default=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        app_label = 'tickets'
        ordering = ['ticket_type', 'name']

    def __str__(self):
        scope = self.tenant.name if self.tenant else "Platform"
        return f"{self.name} ({scope})"


class CannedResponse(models.Model):
    """
    Predefined responses for support staff to quickly reply to common issues.
    """
    tenant = models.ForeignKey(
        Tenant,
        on_delete=models.CASCADE,
        related_name='canned_responses',
        null=True,
        blank=True,
        help_text="Tenant this response belongs to. Null for platform-wide responses."
    )
    title = models.CharField(max_length=100, help_text="Short title for easy selection.")
    content = models.TextField(help_text="The response content. Can include placeholders.")
    category = models.CharField(
        max_length=50,
        choices=Ticket.Category.choices,
        blank=True,
        help_text="Category this response is most relevant to."
    )
    is_active = models.BooleanField(default=True)
    use_count = models.PositiveIntegerField(default=0, help_text="Number of times this response was used.")
    created_by = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        null=True,
        related_name='created_canned_responses',
    )
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        app_label = 'tickets'
        ordering = ['-use_count', 'title']

    def __str__(self):
        scope = self.tenant.name if self.tenant else "Platform"
        return f"{self.title} ({scope})"

class TicketComment(models.Model):
    """
    Represents a comment or update on a support ticket.
    """

    class Source(models.TextChoices):
        WEB = 'WEB', _('Web Interface')
        EMAIL = 'EMAIL', _('Email Reply')
        API = 'API', _('API')

    ticket = models.ForeignKey(
        Ticket,
        on_delete=models.CASCADE,
        related_name='comments',
        help_text="The ticket this comment belongs to."
    )
    author = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        related_name='ticket_comments',
        null=True,
        help_text="The user who wrote this comment."
    )
    comment_text = models.TextField(help_text="The content of the comment.")
    created_at = models.DateTimeField(auto_now_add=True)
    is_internal = models.BooleanField(
        default=False,
        help_text="If true, this comment is only visible to internal staff/platform admins."
    )
    source = models.CharField(
        max_length=10,
        choices=Source.choices,
        default=Source.WEB,
        help_text="How this comment was created (web, email, API)."
    )
    # Link to incoming email if created from email
    incoming_email = models.ForeignKey(
        'IncomingTicketEmail',
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='created_comments',
        help_text="The incoming email that created this comment."
    )
    # External author info (for comments from non-registered users via email)
    external_author_email = models.EmailField(
        null=True,
        blank=True,
        help_text="Email of external author (when author is null)."
    )
    external_author_name = models.CharField(
        max_length=255,
        blank=True,
        default='',
        help_text="Name of external author (when author is null)."
    )

    class Meta:
        app_label = 'tickets'
        ordering = ['created_at']

    @property
    def author_display_name(self):
        """Return the display name for the comment author."""
        if self.author:
            return self.author.get_full_name() or self.author.email
        elif self.external_author_name:
            return self.external_author_name
        elif self.external_author_email:
            return self.external_author_email
        return 'Unknown'

    @property
    def author_email(self):
        """Return the email for the comment author."""
        if self.author:
            return self.author.email
        return self.external_author_email

    def __str__(self):
        author_str = self.author.email if self.author else (self.external_author_email or 'Unknown')
        return f"Comment on Ticket #{self.ticket.id} by {author_str} at {self.created_at.strftime('%Y-%m-%d %H:%M')}"


class IncomingTicketEmail(models.Model):
    """
    Logs all incoming emails for ticket replies.
    Provides audit trail and helps with debugging.
    """

    class ProcessingStatus(models.TextChoices):
        PENDING = 'PENDING', _('Pending')
        PROCESSED = 'PROCESSED', _('Processed')
        FAILED = 'FAILED', _('Failed')
        SPAM = 'SPAM', _('Marked as Spam')
        NO_MATCH = 'NO_MATCH', _('No Matching Ticket')
        DUPLICATE = 'DUPLICATE', _('Duplicate')

    # Email metadata
    message_id = models.CharField(
        max_length=255,
        unique=True,
        help_text="Email Message-ID header for deduplication"
    )
    from_address = models.EmailField(
        help_text="Sender email address"
    )
    from_name = models.CharField(
        max_length=255,
        blank=True,
        default='',
        help_text="Sender display name"
    )
    to_address = models.EmailField(
        help_text="Recipient email address (our support address)"
    )
    subject = models.CharField(
        max_length=500,
        help_text="Email subject line"
    )

    # Email content
    body_text = models.TextField(
        blank=True,
        default='',
        help_text="Plain text email body"
    )
    body_html = models.TextField(
        blank=True,
        default='',
        help_text="HTML email body"
    )
    extracted_reply = models.TextField(
        blank=True,
        default='',
        help_text="Extracted reply text (without quoted content)"
    )

    # Headers for debugging
    raw_headers = models.JSONField(
        default=dict,
        blank=True,
        help_text="Raw email headers for debugging"
    )

    # Ticket matching
    ticket = models.ForeignKey(
        Ticket,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='incoming_emails',
        help_text="Matched ticket (if found)"
    )
    matched_user = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='incoming_ticket_emails',
        help_text="User matched by email address"
    )
    email_address = models.ForeignKey(
        'TicketEmailAddress',
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='incoming_emails',
        help_text="Email address configuration that received this email"
    )
    ticket_id_from_email = models.CharField(
        max_length=50,
        blank=True,
        default='',
        help_text="Ticket ID extracted from email address or subject"
    )

    # Processing status
    processing_status = models.CharField(
        max_length=20,
        choices=ProcessingStatus.choices,
        default=ProcessingStatus.PENDING,
        help_text="Current processing status"
    )
    error_message = models.TextField(
        blank=True,
        default='',
        help_text="Error details if processing failed"
    )

    # Timestamps
    email_date = models.DateTimeField(
        help_text="Date from email headers"
    )
    received_at = models.DateTimeField(
        auto_now_add=True,
        help_text="When we received/processed this email"
    )
    processed_at = models.DateTimeField(
        null=True,
        blank=True,
        help_text="When processing completed"
    )

    class Meta:
        app_label = 'tickets'
        ordering = ['-received_at']
        indexes = [
            models.Index(fields=['message_id']),
            models.Index(fields=['from_address']),
            models.Index(fields=['processing_status']),
            models.Index(fields=['ticket']),
        ]

    def __str__(self):
        return f"Email from {self.from_address}: {self.subject[:50]}..."

    def mark_processed(self, ticket=None, user=None):
        """Mark email as successfully processed."""
        self.processing_status = self.ProcessingStatus.PROCESSED
        self.processed_at = timezone.now()
        if ticket:
            self.ticket = ticket
        if user:
            self.matched_user = user
        self.save()

    def mark_failed(self, error_message: str):
        """Mark email as failed to process."""
        self.processing_status = self.ProcessingStatus.FAILED
        self.error_message = error_message
        self.processed_at = timezone.now()
        self.save()

    def mark_no_match(self):
        """Mark email as having no matching ticket."""
        self.processing_status = self.ProcessingStatus.NO_MATCH
        self.processed_at = timezone.now()
        self.save()


class TicketEmailAddress(models.Model):
    """
    Email address configuration for ticket management.
    Can be tied to a business (tenant) or platform-wide (tenant=null).
    Each business/platform can have multiple email addresses with their own IMAP/SMTP settings.
    """
    tenant = models.ForeignKey(
        Tenant,
        on_delete=models.CASCADE,
        related_name='ticket_email_addresses',
        null=True,
        blank=True,
        help_text="Business this email address belongs to (null for platform-wide)"
    )

    # Display information
    display_name = models.CharField(
        max_length=100,
        help_text="Display name (e.g., 'Support', 'Billing', 'Sales')"
    )
    email_address = models.EmailField(
        help_text="Email address for sending/receiving tickets"
    )
    color = models.CharField(
        max_length=7,
        default='#3b82f6',
        help_text="Hex color code for visual identification (e.g., #3b82f6)"
    )

    # IMAP settings (inbound)
    imap_host = models.CharField(
        max_length=255,
        help_text="IMAP server hostname (e.g., imap.gmail.com)"
    )
    imap_port = models.IntegerField(
        default=993,
        help_text="IMAP port (993 for SSL, 143 for non-SSL)"
    )
    imap_use_ssl = models.BooleanField(
        default=True,
        help_text="Use SSL/TLS for IMAP"
    )
    imap_username = models.CharField(
        max_length=255,
        help_text="IMAP username (usually email address)"
    )
    imap_password = models.CharField(
        max_length=255,
        help_text="IMAP password or app-specific password"
    )
    imap_folder = models.CharField(
        max_length=100,
        default='INBOX',
        help_text="IMAP folder to monitor"
    )

    # SMTP settings (outbound)
    smtp_host = models.CharField(
        max_length=255,
        help_text="SMTP server hostname (e.g., smtp.gmail.com)"
    )
    smtp_port = models.IntegerField(
        default=587,
        help_text="SMTP port (587 for TLS, 465 for SSL)"
    )
    smtp_use_tls = models.BooleanField(
        default=True,
        help_text="Use STARTTLS for SMTP"
    )
    smtp_use_ssl = models.BooleanField(
        default=False,
        help_text="Use SSL/TLS for SMTP (port 465)"
    )
    smtp_username = models.CharField(
        max_length=255,
        help_text="SMTP username (usually email address)"
    )
    smtp_password = models.CharField(
        max_length=255,
        help_text="SMTP password or app-specific password"
    )

    # Status and tracking
    is_active = models.BooleanField(
        default=True,
        help_text="Whether this email address is actively checked"
    )
    is_default = models.BooleanField(
        default=False,
        help_text="Default email for new tickets in this business"
    )
    last_check_at = models.DateTimeField(
        null=True,
        blank=True,
        help_text="When emails were last checked for this address"
    )
    last_error = models.TextField(
        blank=True,
        default='',
        help_text="Last error message if any"
    )
    emails_processed_count = models.IntegerField(
        default=0,
        help_text="Total number of emails processed for this address"
    )

    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        app_label = 'tickets'
        ordering = ['-is_default', 'display_name']
        unique_together = [['tenant', 'email_address']]
        indexes = [
            models.Index(fields=['tenant', 'is_active']),
            models.Index(fields=['email_address']),
        ]
        verbose_name = 'Ticket Email Address'
        verbose_name_plural = 'Ticket Email Addresses'

    def __str__(self):
        return f"{self.display_name} <{self.email_address}> ({self.tenant.name})"

    def save(self, *args, **kwargs):
        # Ensure only one default per tenant
        if self.is_default:
            TicketEmailAddress.objects.filter(
                tenant=self.tenant,
                is_default=True
            ).exclude(pk=self.pk).update(is_default=False)
        super().save(*args, **kwargs)

    def is_imap_configured(self):
        """Check if IMAP settings are properly configured."""
        return bool(self.imap_host and self.imap_username and self.imap_password)

    def is_smtp_configured(self):
        """Check if SMTP settings are properly configured."""
        return bool(self.smtp_host and self.smtp_username and self.smtp_password)

    def is_fully_configured(self):
        """Check if both IMAP and SMTP are configured."""
        return self.is_imap_configured() and self.is_smtp_configured()