"""
Communication Services - Twilio Conversations Integration

Provides masked phone/SMS communication between staff and customers.
CRITICAL: teardown_session() must call Twilio API to close conversations,
not just update local database, to prevent ongoing charges.
"""
from twilio.rest import Client
from django.conf import settings
from django.utils import timezone
from .models import CommunicationSession
import logging

logger = logging.getLogger(__name__)


class TwilioService:
    """
    Service for Twilio Conversations (masked chat/SMS).
    
    Enables staff and customers to communicate without exposing
    personal phone numbers. Messages are routed through Twilio.
    """
    
    def __init__(self):
        """Initialize Twilio client"""
        self.client = Client(
            settings.TWILIO_ACCOUNT_SID,
            settings.TWILIO_AUTH_TOKEN
        )
    
    def create_masked_session(
        self,
        event,
        staff_phone,
        customer_phone,
        language_code='en'
    ):
        """
        Create a masked communication session for an event.

        Creates a Twilio Conversation and adds both staff and customer
        as participants. Messages are routed through Twilio without
        exposing phone numbers.

        Args:
            event: schedule.Event instance
            staff_phone: Staff member's phone (E.164 format)
            customer_phone: Customer's phone (E.164 format)
            language_code: Language for SMS templates (en/es/fr/de)

        Returns:
            CommunicationSession instance

        Raises:
            TwilioRestException: On API errors
            PermissionError: If tenant doesn't have masked calling feature
        """
        from django.db import connection
        from smoothschedule.identity.core.models import Tenant
        from rest_framework.exceptions import PermissionDenied

        # Check feature permission
        # Get tenant from current schema
        schema_name = connection.schema_name
        if schema_name and schema_name != 'public':
            try:
                # Switch to public schema temporarily to query Tenant
                with connection.cursor() as cursor:
                    cursor.execute('SET search_path TO public')
                    tenant = Tenant.objects.get(schema_name=schema_name)
                    cursor.execute(f'SET search_path TO {schema_name}')

                if not tenant.has_feature('can_use_masked_phone_numbers'):
                    raise PermissionDenied(
                        "Your current plan does not include Masked Calling. "
                        "Please upgrade your subscription to access this feature."
                    )
            except Tenant.DoesNotExist:
                logger.warning(f"Tenant not found for schema: {schema_name}")
                # Continue anyway - may be a system operation
        #  Step 1: Create Twilio Conversation
        conversation = self.client.conversations.v1.conversations.create(
            friendly_name=f"Event: {event.title} (ID: {event.id})",
            unique_name=f"event_{event.id}_{timezone.now().timestamp()}",
        )
        
        logger.info(
            f"Created Twilio Conversation: {conversation.sid}",
            extra={'event_id': event.id}
        )
        
        # Step 2: Add Staff Participant (SMS)
        staff_participant = conversation.participants.create(
            messaging_binding_address=staff_phone,
            messaging_binding_proxy_address=settings.TWILIO_PROXY_NUMBER,
        )
        
        logger.info(
            f"Added staff participant: {staff_participant.sid}",
            extra={'phone': staff_phone[:6] + '****'}  # Masked for logging
        )
        
        # Step 3: Add Customer Participant (SMS)
        customer_participant = conversation.participants.create(
            messaging_binding_address=customer_phone,
            messaging_binding_proxy_address=settings.TWILIO_PROXY_NUMBER,
        )
        
        logger.info(
            f"Added customer participant: {customer_participant.sid}",
            extra={'phone': customer_phone[:6] + '****'}
        )
        
        # Step 4: Send initial message (localized)
        # FUTURE: Load SMS templates based on language_code
        welcome_message = self._get_welcome_message(language_code, event)
        conversation.messages.create(
            body=welcome_message,
            author='system'
        )
        
        # Step 5: Create local session record
        session = CommunicationSession.objects.create(
            event=event,
            twilio_conversation_sid=conversation.sid,
            is_active=True,
            staff_phone=staff_phone,
            customer_phone=customer_phone,
            language_code=language_code,
            staff_participant_sid=staff_participant.sid,
            customer_participant_sid=customer_participant.sid,
        )
        
        logger.info(
            f"Created CommunicationSession: {session.id}",
            extra={'event_id': event.id, 'conversation_sid': conversation.sid}
        )
        
        return session
    
    def teardown_session(self, event):
        """
        Close and cleanup a communication session.
        
        CRITICAL: This MUST call the Twilio API to actually close/delete
        the conversation. Just updating the local DB is NOT sufficient
        and will result in ongoing charges.
        
        Args:
            event: schedule.Event instance
        
        Returns:
            bool: True if successful
        """
        try:
            # Fetch the session
            session = CommunicationSession.objects.get(
                event=event,
                is_active=True
            )
            
            #  CRITICAL: Actually call Twilio API to close conversation
            # This prevents ongoing message charges
            conversation = self.client.conversations.v1.conversations(
                session.twilio_conversation_sid
            )
            
            # Delete the conversation (closes it and removes all participants)
            conversation.delete()
            
            logger.info(
                f"Deleted Twilio Conversation: {session.twilio_conversation_sid}",
                extra={'event_id': event.id}
            )
            
            # Now update local database
            session.is_active = False
            session.closed_at = timezone.now()
            session.save()
            
            logger.info(
                f"Closed CommunicationSession: {session.id}",
                extra={'event_id': event.id}
            )
            
            return True
            
        except CommunicationSession.DoesNotExist:
            logger.warning(f"No active session found for Event {event.id}")
            return False
        except Exception as e:
            logger.error(
                f"Error tearing down session for Event {event.id}: {str(e)}",
                exc_info=e
            )
            return False
    
    def send_message(self, session, message_body, author='staff'):
        """
        Send a message in an existing conversation.
        
        Args:
            session: CommunicationSession instance
            message_body: Message text
            author: 'staff' or 'customer'
        """
        if not session.is_active:
            raise ValueError("Cannot send message to inactive session")
        
        conversation = self.client.conversations.v1.conversations(
            session.twilio_conversation_sid
        )
        
        message = conversation.messages.create(
            body=message_body,
            author=author
        )
        
        logger.info(
            f"Sent message in conversation {session.twilio_conversation_sid}",
            extra={'author': author}
        )
        
        return message
    
    def _get_welcome_message(self, language_code, event):
        """
        Get localized welcome message.
        
        FUTURE: Load from database or template files based on language_code.
        Currently returns English only.
        
        Args:
            language_code: Language preference (en/es/fr/de)
            event: Event instance
        
        Returns:
            str: Localized welcome message
        """
        # STUB: Future implementation would load from i18n templates
        templates = {
            'en': f"Hi! This is a secure line for your appointment: {event.title}. Reply to this message to communicate.",
            'es': f"¡Hola! Esta es una línea segura para su cita: {event.title}. Responda a este mensaje para comunicarse.",
            'fr': f"Bonjour! Ceci est une ligne sécurisée pour votre rendez-vous: {event.title}. Répondez à ce message pour communiquer.",
            'de': f"Hallo! Dies ist eine sichere Leitung für Ihren Termin: {event.title}. Antworten Sie auf diese Nachricht, um zu kommunizieren.",
        }
        
        return templates.get(language_code, templates['en'])


# Helper function
def get_twilio_service():
    """Factory function to get TwilioService"""
    return TwilioService()
