import os
import smtplib
import requests
import base64
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from typing import Dict, Any, Optional
from connectors.firebase.firebase import Firebase
import logging

logger = logging.getLogger(__name__)
fb = Firebase(host=os.environ.get("FIREBASE_HOST"))


def send_email_via_gmail(
    channel_config: Dict[str, Any],
    to_email: str,
    subject: str,
    html_content: str,
    text_content: Optional[str] = None
) -> Dict[str, Any]:
    """
    Send email via Gmail SMTP
    
    Args:
        channel_config: Email channel configuration from Firebase
        to_email: Recipient email address
        subject: Email subject
        html_content: HTML email body
        text_content: Plain text email body (optional)
    
    Returns:
        Dict with success status and message
    """
    try:
        smtp_server = channel_config.get("smtp_server", "smtp.gmail.com")
        smtp_port = channel_config.get("smtp_port", 587)
        smtp_username = channel_config.get("smtp_username") or channel_config.get("from_email")
        smtp_password = channel_config.get("smtp_password")
        encryption = channel_config.get("encryption", "TLS")
        from_email = channel_config.get("from_email")
        from_name = channel_config.get("from_name", "")
        
        if not smtp_username or not smtp_password:
            return {"success": False, "error": "SMTP username or password not configured"}
        
        # Create message
        msg = MIMEMultipart('alternative')
        msg['Subject'] = subject
        msg['From'] = f"{from_name} <{from_email}>" if from_name else from_email
        msg['To'] = to_email
        
        # Add text and HTML parts
        if text_content:
            text_part = MIMEText(text_content, 'plain')
            msg.attach(text_part)
        
        html_part = MIMEText(html_content, 'html')
        msg.attach(html_part)
        
        # Connect to SMTP server
        if encryption.upper() == "SSL":
            server = smtplib.SMTP_SSL(smtp_server, smtp_port)
        else:
            server = smtplib.SMTP(smtp_server, smtp_port)
            server.starttls()
        
        # Login and send
        server.login(smtp_username, smtp_password)
        server.send_message(msg)
        server.quit()
        
        logger.info(f"Email sent successfully via Gmail to {to_email}")
        return {"success": True, "message": "Email sent successfully"}
        
    except smtplib.SMTPAuthenticationError as e:
        logger.error(f"Gmail SMTP authentication error: {e}")
        return {"success": False, "error": f"SMTP authentication failed: {str(e)}"}
    except smtplib.SMTPException as e:
        logger.error(f"Gmail SMTP error: {e}")
        return {"success": False, "error": f"SMTP error: {str(e)}"}
    except Exception as e:
        logger.error(f"Error sending email via Gmail: {e}")
        return {"success": False, "error": f"Failed to send email: {str(e)}"}


def send_email_via_thaibulksms(
    channel_config: Dict[str, Any],
    to_email: str,
    subject: str,
    html_content: str,
    text_content: Optional[str] = None
) -> Dict[str, Any]:
    """
    Send email via ThaiBulkSMS API
    
    Args:
        channel_config: Email channel configuration from Firebase
        to_email: Recipient email address
        subject: Email subject
        html_content: HTML email body
        text_content: Plain text email body (optional)
    
    Returns:
        Dict with success status and message
    """
    try:
        api_key = channel_config.get("api_key")
        api_secret = channel_config.get("api_secret")
        from_email = channel_config.get("from_email")
        from_name = channel_config.get("from_name", "")
        
        if not api_key or not api_secret:
            return {"success": False, "error": "ThaiBulkSMS API key or secret not configured"}
        
        # ThaiBulkSMS Email API endpoint
        # Documentation: https://developer.thaibulksms.com/reference/transactionalcontroller_send
        # Error message shows send_template requires template_uuid, mail_to, mail_from
        # and does not accept: to, from, from_name, html, text
        # Try using /send endpoint for direct email sending (without template)
        api_url = "https://email-api.thaibulksms.com/email/v1/send"
        
        # Prepare request with Basic Authentication
        # ThaiBulkSMS uses Basic Auth with api-key as username and api-secret as password
        credentials = f"{api_key}:{api_secret}"
        encoded_credentials = base64.b64encode(credentials.encode()).decode()
        
        headers = {
            "Authorization": f"Basic {encoded_credentials}",
            "Content-Type": "application/json"
        }
        
        # ThaiBulkSMS API payload format
        # Based on error message: use mail_to and mail_from (not to/from)
        # Format mail_from with name if provided
        mail_from_value = f"{from_name} <{from_email}>" if from_name else from_email
        
        payload = {
            "mail_to": to_email,
            "mail_from": mail_from_value,
            "subject": subject,
            "html": html_content,
            "text": text_content or html_content
        }
        
        # Make API request
        response = requests.post(api_url, json=payload, headers=headers, timeout=30)
        
        if response.status_code == 200:
            logger.info(f"Email sent successfully via ThaiBulkSMS to {to_email}")
            return {"success": True, "message": "Email sent successfully", "response": response.json()}
        else:
            error_msg = f"ThaiBulkSMS API error: {response.status_code} - {response.text}"
            logger.error(error_msg)
            return {"success": False, "error": error_msg}
            
    except requests.exceptions.RequestException as e:
        logger.error(f"ThaiBulkSMS API request error: {e}")
        return {"success": False, "error": f"API request failed: {str(e)}"}
    except Exception as e:
        logger.error(f"Error sending email via ThaiBulkSMS: {e}")
        return {"success": False, "error": f"Failed to send email: {str(e)}"}


def send_email_via_infobip(
    channel_config: Dict[str, Any],
    to_email: str,
    subject: str,
    html_content: str,
    text_content: Optional[str] = None
) -> Dict[str, Any]:
    """
    Send email via Infobip API (for backward compatibility)
    
    Args:
        channel_config: Email channel configuration from Firebase
        to_email: Recipient email address
        subject: Email subject
        html_content: HTML email body
        text_content: Plain text email body (optional)
    
    Returns:
        Dict with success status and message
    """
    try:
        infobip_api_key = os.environ.get('INFOBIP_API_KEY')
        infobip_base_url = os.environ.get('INFOBIP_BASE_URL', '8v9rp3.api.infobip.com')
        
        if not infobip_api_key:
            return {"success": False, "error": "INFOBIP_API_KEY not configured"}
        
        from_email = channel_config.get("from_email")
        
        api_url = f"https://{infobip_base_url}/email/3/send"
        
        headers = {
            "Authorization": f"App {infobip_api_key}",
            "Content-Type": "application/json"
        }
        
        payload = {
            "from": from_email,
            "to": [to_email],
            "subject": subject,
            "text": text_content or html_content,
            "html": html_content
        }
        
        response = requests.post(api_url, json=payload, headers=headers, timeout=30)
        
        if response.status_code == 200:
            logger.info(f"Email sent successfully via Infobip to {to_email}")
            return {"success": True, "message": "Email sent successfully", "response": response.json()}
        else:
            error_msg = f"Infobip API error: {response.status_code} - {response.text}"
            logger.error(error_msg)
            return {"success": False, "error": error_msg}
            
    except requests.exceptions.RequestException as e:
        logger.error(f"Infobip API request error: {e}")
        return {"success": False, "error": f"API request failed: {str(e)}"}
    except Exception as e:
        logger.error(f"Error sending email via Infobip: {e}")
        return {"success": False, "error": f"Failed to send email: {str(e)}"}


def send_test_email(
    property_id: str,
    content_id: str,
    channel_id: str,
    to_email: str
) -> Dict[str, Any]:
    """
    Send test email using specified template and channel
    
    Args:
        property_id: Property ID
        content_id: Email template content ID
        channel_id: Email channel ID
        to_email: Recipient email address
    
    Returns:
        Dict with success status and message/error
    """
    try:
        # Get email template content
        content_ref = fb.db.reference().child(f"account/{property_id}/content/email/{content_id}")
        template = content_ref.get()
        
        if not template:
            return {"success": False, "error": f"Email template {content_id} not found"}
        
        subject = template.get("subject", "")
        body = template.get("body", "")
        is_html = template.get("is_html", True)
        
        if not subject:
            return {"success": False, "error": "Email template missing subject"}
        
        if not body:
            return {"success": False, "error": "Email template missing body"}
        
        # Get channel configuration
        channel_ref = fb.db.reference().child(f"property/{property_id}/channel/email/{channel_id}")
        channel_config = channel_ref.get()
        
        if not channel_config:
            return {"success": False, "error": f"Email channel {channel_id} not found"}
        
        if channel_config.get("status") != "active":
            return {"success": False, "error": f"Email channel {channel_id} is not active"}
        
        provider = channel_config.get("provider", "infobip")
        
        # Prepare content
        html_content = body if is_html else f"<html><body><pre>{body}</pre></body></html>"
        text_content = body if not is_html else None
        
        # Route to appropriate sender
        if provider == "gmail":
            result = send_email_via_gmail(channel_config, to_email, subject, html_content, text_content)
        elif provider == "thaibulksms":
            result = send_email_via_thaibulksms(channel_config, to_email, subject, html_content, text_content)
        elif provider == "infobip":
            result = send_email_via_infobip(channel_config, to_email, subject, html_content, text_content)
        else:
            return {"success": False, "error": f"Unsupported email provider: {provider}"}
        
        return result
        
    except Exception as e:
        logger.error(f"Error in send_test_email: {e}")
        return {"success": False, "error": f"Failed to send test email: {str(e)}"}
