from django.db import models
from django.utils import timezone

from apps.companies.constants import BotName
from coresite.mixin import AbstractTimeStampModel
from apps.core.models import User
from apps.companies.models import Company
from apps.calls.constants import (
    BotType, CRON_JOB_STATUS,
    NotificationType,
    CallTimeCategory,
)


class Call(AbstractTimeStampModel):
    """Call object."""

    TRANSFER_STATUS_CHOICES = [
        (0, 'Not Transferred'),
        (1, 'Transferred'),
        (2, 'Transfer Failed'),
    ]

    BOOKING_INTENT_STATUS_CHOICES = [
        (CRON_JOB_STATUS['NOT_PROCESSED'], 'NOT_PROCESSED'),
        (CRON_JOB_STATUS['PROCESSING'], 'PROCESSING'),
        (CRON_JOB_STATUS['COMPLETED'], 'COMPLETED'),
        (CRON_JOB_STATUS['FAILED'], 'FAILED'),
    ]

    BOOKING_INTENT_CHOICES = [
        (0, 'No Intent for booking'),
        (1, 'Intent for booking'),
    ]

    caller_name = models.CharField(max_length=255, blank=True, null=True)
    from_number = models.CharField(max_length=255)
    to_number = models.CharField(max_length=255)
    transfer_status = models.SmallIntegerField(
        choices=TRANSFER_STATUS_CHOICES,
        default=0
    )
    call_time_category = models.SmallIntegerField(
        null=True,
        choices=CallTimeCategory.model_choices()
    )
    transfer_number = models.CharField(max_length=255, blank=True, null=True)
    transfer_user = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        null=True,
        blank=True
    )
    # customer = models.ForeignKey(
    #     'customers.Customer',
    #     null=True,
    #     blank=True,
    #     on_delete=models.SET_NULL,
    #     related_name='calls',
    #     db_index=True,
    # )
    company = models.ForeignKey(
        Company,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
    )
    dealership = models.ForeignKey(
        Company,
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="calls",
    )
    status = models.CharField(max_length=255)
    transcript = models.TextField(blank=True)
    transcript_complete = models.TextField(blank=True, null=True)
    summary = models.TextField(blank=True)
    bot_type = models.SmallIntegerField(
        null=True,
        choices=BotType.model_choices(),
    )
    sentiment = models.SmallIntegerField(null=True)
    duration = models.DecimalField(max_digits=5, decimal_places=2)
    cost = models.DecimalField(max_digits=5, decimal_places=2)
    call_id = models.CharField(max_length=255)
    twilio_call_sid = models.CharField(max_length=255)
    twilio_recording_text = models.TextField(blank=True, null=True)
    booking_datetime = models.DateTimeField(null=True, blank=True)
    booking_intent = models.SmallIntegerField(
        choices=BOOKING_INTENT_CHOICES,
        default=0
    )
    booking_intent_status = models.SmallIntegerField(
        null=True,
        choices=BOOKING_INTENT_STATUS_CHOICES
    )
    read_by = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="read_calls"
    )
    read_at = models.DateTimeField(null=True, blank=True)

    def __str__(self):
        return f"Call {self.call_id} | {self.from_number} → {self.to_number}"

class TonyCall(AbstractTimeStampModel):
    """Call object."""
    end_reason = models.CharField(max_length=255)
    call_id = models.CharField(max_length=255)
    recording_url = models.CharField(max_length=255)
    transcript = models.TextField(blank=True)
    call_date_time = models.DateTimeField(null=True, blank=True)
    intention = models.CharField(max_length=255)
    rescheduled  = models.CharField(max_length=255)
    booking_datetime = models.DateTimeField(null=True, blank=True)
    company = models.ForeignKey(Company, on_delete=models.SET_NULL, null=True, blank=True)
    status = models.CharField(max_length=255)
    called_to = models.CharField(max_length=255)
    called_number = models.CharField(max_length=255)

    def __str__(self):
        return f"TonyCall {self.call_id}"

    class Meta:
        db_table = "vtony_calls"

class CallActivity(AbstractTimeStampModel):
    ACTION_CHOICES = [
        ('READ', 'read'),
        ('PLAY', 'played'),
    ]

    call = models.ForeignKey(Call, on_delete=models.CASCADE, related_name='activities')
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='call_activities')
    action = models.CharField(max_length=10, choices=ACTION_CHOICES)
    performed_at = models.DateTimeField(null=True)
    duration_played = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True)

    class Meta:
        ordering = ['-created_at']

    def __str__(self):
        return f"{self.user} {self.action.lower()} {self.call} at {self.created_at}"

class UserMessage(AbstractTimeStampModel):
    recipient = models.ForeignKey(
        User, 
        on_delete=models.CASCADE, 
        related_name='received_messages'
    )

    company = models.ForeignKey(
        Company,
        on_delete=models.CASCADE,
        null=True, blank=True,
        related_name='messages',
        help_text="The company this message belongs to"
    )

    customer_name = models.CharField(
        max_length=255,
        blank=True,
        null=True,
        help_text="Name of the customer who sent or is related to this message."
    )
    customer_number = models.CharField(
        max_length=20,
        blank=True,
        null=True,
        help_text="Customer phone number. Store as text to preserve formatting."
    )
    twilio_call_sid = models.CharField(
        max_length=255,
        unique=True,
        blank=True,
        null=True,
        help_text="To update record-off-time-message",
    )
    subject = models.CharField(max_length=255, blank=True)
    body = models.TextField()
    is_read = models.BooleanField(default=False)
    read_at = models.DateTimeField(null=True, blank=True)

    class Meta:
        ordering = ['-created_at']

    def mark_as_read(self):
        if not self.is_read:
            self.is_read = True
            self.read_at = timezone.now()
            self.save(update_fields=['is_read', 'read_at'])

    def __str__(self):
        return (f'Message from {self.customer_name} to '
                f'{self.recipient.profile.full_name} | '
                f'Read: {self.is_read}')

class Notification(models.Model):
    recipient = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name="notifications"
    )

    company = models.ForeignKey(
        Company,
        on_delete=models.CASCADE,
        null=True, blank=True,
        related_name="notifications",
        help_text="The company this notification belongs to"
    )

    notification_type = models.SmallIntegerField(
        choices=NotificationType.model_choices(),
        db_index=True
    )

    call = models.ForeignKey(
        Call,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="notifications",
        help_text="Optional reference to the call this notification is about"
    )

    title = models.CharField(max_length=255, blank=True, null=True)
    message = models.TextField(blank=True, null=True)

    is_read = models.BooleanField(default=False)
    read_at = models.DateTimeField(blank=True, null=True)

    created_at = models.DateTimeField(auto_now_add=True)

    def mark_as_read(self):
        if not self.is_read:
            self.is_read = True
            self.read_at = timezone.now()
            self.save(update_fields=["is_read", "read_at"])
    
    class Meta:
        indexes = [
            models.Index(fields=["recipient", "is_read"]),
            models.Index(fields=["recipient", "created_at"]),
        ]
        
        ordering = ['-created_at']

    def __str__(self):
        name = getattr(self.recipient.profile, "full_name", self.recipient.username)
        return f"Notification to {name} | Read: {self.is_read}"

class BotInstructionTemplate(AbstractTimeStampModel):
    """
    Stores all bot dynamic messages & routing instructions in DB.
    No hard-coded text in Python.
    """

    company = models.ForeignKey(
        Company,
        on_delete=models.CASCADE,
        related_name="bot_instruction_templates"
    )

    bot_name = models.CharField(
        max_length=50,
    )

    template_type = models.CharField(
        max_length=50,
    )

    title = models.CharField(
        max_length=100,
        help_text="Short admin-friendly name (e.g. 'Default Advisor Transfer')"
    )

    content = models.TextField(
        help_text=(
            "Use placeholders like:\n"
            "{advisor_name}, {advisor_phone}, {dealership_name}, {dealership_phone}"
        )
    )

    is_active = models.BooleanField(default=True)

    class Meta:
        unique_together = ("company", "bot_name", "template_type")
        ordering = ["company", "bot_name", "template_type"]

    def __str__(self):
        return f"{self.company.name} | {self.bot_name} | {self.template_type}"
