
import requests
from django.conf import settings
from django.template import Template, Context
from .models import SMSLog, EmailLog, NotificationTemplate
from .email_service import EmailService
import logging

logger = logging.getLogger(__name__)

class NotificationService:
    def __init__(self):
        from settings.utils import get_sms_settings
        sms_settings = get_sms_settings()
        self.sms_api_url = sms_settings.get('api_url', '')
        self.sms_api_key = sms_settings.get('api_key', '')
        self.sms_partner_id = sms_settings.get('partner_id', '')
        self.sms_short_code = sms_settings.get('short_code', '')
        self.sms_method = sms_settings.get('method', 'POST')
        self.sms_phone_parameter = sms_settings.get('phone_parameter', 'phone')
        self.sms_message_parameter = sms_settings.get('message_parameter', 'message')
        
        # Initialize email service
        self.email_service = EmailService()
    
    def send_email(self, email, subject, message, template_type=None, customer_id=None, 
                  payment_id=None, invoice_id=None, sent_by=None, recipient_name='',
                  context_data=None, html_content=None):
        """Send email using the new email service"""
        success, error_msg = self.email_service.send_email(
            recipient_email=email,
            subject=subject,
            content=message,
            email_type=template_type or 'general',
            recipient_name=recipient_name,
            sent_by=sent_by,
            context_data=context_data,
            customer_id=customer_id,
            payment_id=payment_id,
            invoice_id=invoice_id,
            template_type=template_type,
            html_content=html_content
        )
        return success
    
    def send_sms(self, phone_number, message, template_type=None, customer_id=None, payment_id=None, invoice_id=None, sent_by=None, recipient_name=''):
        """Send SMS using TextSMS API"""
        try:
            # Clean and format phone number
            phone_number = str(phone_number).strip().replace(' ', '').replace('-', '')
            
            # Format phone number to proper format
            if phone_number.startswith('0'):
                phone_number = '254' + phone_number[1:]
            elif phone_number.startswith('+254'):
                phone_number = phone_number[1:]
            elif phone_number.startswith('+'):
                phone_number = phone_number[1:]
            elif not phone_number.startswith('254'):
                phone_number = '254' + phone_number
            
            # Validate final format
            if not phone_number.startswith('254') or len(phone_number) != 12:
                raise ValueError(f"Invalid phone number format after processing: {phone_number}")
            
            # Get template if provided
            template_used = None
            if template_type:
                try:
                    template_used = NotificationTemplate.objects.get(template_type=template_type, is_active=True)
                except NotificationTemplate.DoesNotExist:
                    pass
            
            # Create SMS log
            sms_log = SMSLog.objects.create(
                recipient_phone=phone_number,
                recipient_name=recipient_name,
                message=message,
                template_used=template_used,
                customer_id=customer_id,
                payment_id=payment_id,
                invoice_id=invoice_id,
                sent_by=sent_by,
                status='pending'
            )
            
            if not self.sms_api_url or not self.sms_api_key:
                sms_log.status = 'failed'
                sms_log.error_message = 'SMS API not configured'
                sms_log.save()
                return False
            
            # Validate phone number format before API call
            if not phone_number or len(phone_number) < 10:
                sms_log.status = 'failed'
                sms_log.error_message = f'Invalid phone number format: {phone_number}'
                sms_log.save()
                return False
            
            # Prepare API parameters - ensure phone parameter is properly mapped
            api_params = {
                'apikey': self.sms_api_key,
            }
            
            # Set phone parameter (ensure it's not empty and use exact parameter name)
            phone_param_name = self.sms_phone_parameter if self.sms_phone_parameter else 'mobile'
            api_params[phone_param_name] = str(phone_number)  # Ensure it's a string
            
            # Set message parameter
            message_param_name = self.sms_message_parameter if self.sms_message_parameter else 'message'
            api_params[message_param_name] = str(message)  # Ensure it's a string
            
            # Add optional parameters if configured
            if self.sms_partner_id:
                api_params['partnerID'] = self.sms_partner_id
            if self.sms_short_code:
                api_params['shortcode'] = self.sms_short_code
            
            try:
                # Make API request based on method
                if self.sms_method.upper() == 'GET':
                    response = requests.get(self.sms_api_url, params=api_params, timeout=30)
                else:
                    response = requests.post(self.sms_api_url, data=api_params, timeout=30)
                
                # Log the request for debugging (mask sensitive data)
                debug_params = api_params.copy()
                if 'apikey' in debug_params:
                    debug_params['apikey'] = '***masked***'
                logger.info(f"SMS API Request to {self.sms_api_url}")
                logger.info(f"SMS API Parameters: {debug_params}")
                logger.info(f"SMS API Response ({response.status_code}): {response.text}")
                
                if response.status_code == 200:
                    # Try to parse JSON response for more detailed status
                    try:
                        response_data = response.json()
                        # Check for common SMS API error patterns
                        if isinstance(response_data, dict):
                            # Check for TextSMS API response pattern
                            if 'response-code' in response_data:
                                response_code = response_data.get('response-code')
                                if response_code == 1000:  # Success code for TextSMS
                                    sms_log.status = 'sent'
                                    sms_log.save()
                                    logger.info(f"SMS sent successfully to {phone_number}")
                                    return True
                                else:
                                    # Failed with error code
                                    error_msg = response_data.get('response-description', 'Unknown error')
                                    errors = response_data.get('errors', '')
                                    full_error = f"API Error {response_code}: {error_msg}"
                                    if errors:
                                        full_error += f" - {errors}"
                                    
                                    sms_log.status = 'failed'
                                    sms_log.error_message = full_error
                                    sms_log.save()
                                    logger.error(f"SMS failed to {phone_number}: {full_error}")
                                    return False
                            
                            # Check for other common error patterns
                            elif 'error' in response_data or 'status' in response_data:
                                if response_data.get('status') == 'error' or 'error' in response_data:
                                    error_msg = response_data.get('message', response_data.get('error', 'Unknown error'))
                                    sms_log.status = 'failed'
                                    sms_log.error_message = f"API Error: {error_msg}"
                                    sms_log.save()
                                    logger.error(f"SMS failed to {phone_number}: {error_msg}")
                                    return False
                    except ValueError:
                        # Response is not JSON, treat as plain text
                        pass
                    
                    # If we reach here, assume success for 200 status
                    sms_log.status = 'sent'
                    sms_log.save()
                    logger.info(f"SMS sent successfully to {phone_number}")
                    return True
                else:
                    sms_log.status = 'failed'
                    sms_log.error_message = f"HTTP {response.status_code}: {response.text}"
                    sms_log.save()
                    logger.error(f"SMS failed to {phone_number}: HTTP {response.status_code} - {response.text}")
                    return False
                    
            except requests.exceptions.RequestException as e:
                sms_log.status = 'failed'
                sms_log.error_message = f"Network error: {str(e)}"
                sms_log.save()
                logger.error(f"SMS API network error for {phone_number}: {str(e)}")
                return False
                
        except Exception as e:
            logger.error(f"SMS service error: {str(e)}")
            return False
    
    def render_template(self, template_content, context_data):
        """Render template with context data"""
        try:
            template = Template(template_content)
            context = Context(context_data)
            return template.render(context)
        except Exception as e:
            logger.error(f"Error rendering template: {str(e)}")
            return template_content
    
    def send_payment_notification(self, customer, payment, notification_type='payment_received'):
        """Send payment notification via SMS and email"""
        try:
            # Prepare context data
            context_data = {
                'customer_name': customer.full_name,
                'customer_id': customer.customer_id,
                'amount': payment.amount,
                'payment_method': payment.get_payment_method_display(),
                'payment_id': payment.payment_id,
                'invoice_number': payment.invoice.invoice_number if payment.invoice else '',
                'date': payment.created_at.strftime('%Y-%m-%d %H:%M'),
            }
            
            # Send SMS notification
            try:
                sms_template = NotificationTemplate.objects.get(
                    template_type=f'sms_{notification_type}',
                    is_active=True
                )
                sms_message = self.render_template(sms_template.content, context_data)
                self.send_sms(
                    phone_number=customer.phone,
                    message=sms_message,
                    template_type=f'sms_{notification_type}',
                    customer_id=customer.id,
                    payment_id=payment.payment_id,
                    recipient_name=customer.full_name
                )
            except NotificationTemplate.DoesNotExist:
                # Send default SMS
                default_message = f"Payment of KES {payment.amount} received for {customer.full_name}. Thank you!"
                self.send_sms(
                    phone_number=customer.phone,
                    message=default_message,
                    customer_id=customer.id,
                    payment_id=payment.payment_id,
                    recipient_name=customer.full_name
                )
            
            # Send email notification using the new email service
            if notification_type == 'payment_received':
                self.email_service.send_payment_confirmation_email(payment)
            else:
                try:
                    email_template = NotificationTemplate.objects.get(
                        template_type=f'email_{notification_type}',
                        is_active=True
                    )
                    self.send_email(
                        email=customer.email,
                        subject=email_template.subject,
                        message=email_template.content,
                        template_type=f'email_{notification_type}',
                        customer_id=customer.id,
                        payment_id=payment.payment_id,
                        recipient_name=customer.full_name,
                        context_data=context_data
                    )
                except NotificationTemplate.DoesNotExist:
                    # Send default email
                    self.send_email(
                        email=customer.email,
                        subject=f"Payment Confirmation - {payment.payment_id}",
                        message=f"Dear {customer.full_name},\n\nYour payment of KES {payment.amount} has been received.\n\nThank you!",
                        customer_id=customer.id,
                        payment_id=payment.payment_id,
                        recipient_name=customer.full_name
                    )
                
        except Exception as e:
            logger.error(f"Error sending payment notification: {str(e)}")
