import os
import smtplib
import asyncio
import logging
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import random
import string
import traceback
from typing import Optional
from concurrent.futures import ThreadPoolExecutor
import socket
import time
import ssl
from dotenv import load_dotenv

from app.common.constants import EMAIL_CREDENTIALS, SALES_EMAIL_CREDENTIALS

load_dotenv()

logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)  # Make sure logging level is set to show info messages

# ThreadPoolExecutor for non-blocking email sending
executor = ThreadPoolExecutor(max_workers=5)



# def get_email_settings():
#     """Get email settings from environment variables with detailed logging"""
#     settings = {
#         "smtp_server": os.environ.get("SMTP_SERVER"),
#         "smtp_port": os.environ.get("SMTP_PORT"),
#         "smtp_username": os.environ.get("SMTP_USERNAME"),
#         "smtp_password": os.environ.get("SMTP_PASSWORD"),
#         "default_sender": os.environ.get("EMAIL_SENDER"),
#     }

#     # Convert port to integer if it exists and is a valid number
#     if settings["smtp_port"] and settings["smtp_port"].isdigit():
#         settings["smtp_port"] = int(settings["smtp_port"])

#     # Log the settings for debugging
#     logger.info(f"SMTP Server: {settings['smtp_server'] or 'Not set'}")
#     logger.info(f"SMTP Port: {settings['smtp_port'] or 'Not set'}")
#     logger.info(f"SMTP Username: {settings['smtp_username'] or 'Not set'}")
#     logger.info(f"Email Sender: {settings['default_sender'] or 'Not set'}")

#     return settings


def send_email_with_timeout(
    recipient, subject, body, html_body=None, sender_email=None, credentials=None, timeout=30,
):
    """Send email with better timeout handling and diagnostics"""
    start_time = time.time()
    if credentials is None:
        logger.error(f"Cannot send email, missing credentials")
        return False, f"Missing email credentials"

    smtp_server = credentials.get("smtp_server")
    smtp_port = int(credentials.get("smtp_port"))
    smtp_username = credentials.get("smtp_username")
    smtp_password = credentials.get("smtp_password")
    sender_email = credentials.get("sender_email")



    # # Check for missing settings
    # missing_settings = []
    # if not settings["smtp_server"]:
    #     missing_settings.append("SMTP_SERVER")
    # if not settings["smtp_port"]:
    #     missing_settings.append("SMTP_PORT")
    # if not settings["smtp_username"]:
    #     missing_settings.append("SMTP_USERNAME")
    # if not settings["smtp_password"]:
    #     missing_settings.append("SMTP_PASSWORD")
    # if not settings["default_sender"] and not sender_email:
    #     missing_settings.append("EMAIL_SENDER")

    print(f"smtp_server: {smtp_server}")
    print(f"smtp_port: {smtp_port}")
    print(f"smtp_port int: {int(smtp_port)}")
    print(f"smtp_username: {smtp_username}")
    print(f"smtp_password: {smtp_password}")
    print(f"sender_email: {sender_email}")
    
    logger.info(f"smtp_server: {smtp_server}")
    logger.info(f"smtp_port: {smtp_port}")
    logger.info(f"smtp_port int: {int(smtp_port)}")
    logger.info(f"smtp_username: {smtp_username}")
    logger.info(f"smtp_password: {smtp_password}")
    logger.info(f"sender_email: {sender_email}")

    

    # Create message
    message = MIMEMultipart("alternative")
    message["Subject"] = subject
    message["From"] = sender_email
    message["To"] = recipient

    # Attach parts
    message.attach(MIMEText(body, "plain"))
    if html_body:
        message.attach(MIMEText(html_body, "html"))

    # Initialize variables for diagnostics
    connection_time = None
    auth_time = None
    send_time = None
    server = None

    try:
        # Attempt to resolve the SMTP server hostname
        logger.info(f"Resolving SMTP server hostname: {smtp_server}")
        try:
            socket.gethostbyname(smtp_server)
            logger.info(f"Successfully resolved SMTP server hostname")
        except socket.gaierror as e:
            logger.error(f"Failed to resolve SMTP server hostname: {e}")
            return False, f"Failed to resolve SMTP server hostname: {e}"

        # Connect with timeout
        logger.info(
            f"Connecting to SMTP server {smtp_server}:{smtp_port} with timeout {timeout}s"
        )
        conn_start = time.time()

        old_timeout = socket.getdefaulttimeout()
        socket.setdefaulttimeout(timeout)

        try:
            if smtp_port == 465:
                print(
                    f"Connecting to SMTP server {smtp_server}:{smtp_port} using SSL"
                )
                server = smtplib.SMTP_SSL(
                    smtp_server, smtp_port, timeout=timeout
                )
                connection_time = time.time() - conn_start
                print(
                    f"Connected to SMTP server using SSL in {connection_time:.2f}s"
                )

                # No need for STARTTLS with SMTP_SSL
            else:
                # For other ports (like 587), use regular SMTP with STARTTLS
                print(
                    f"Connecting to SMTP server {smtp_server}:{smtp_port} with timeout {timeout}s"
                )
                server = smtplib.SMTP(smtp_server, smtp_port)
                connection_time = time.time() - conn_start
                print(f"Connected to SMTP server in {connection_time:.2f}s")

                # Start TLS for non-SSL connections
                print("Starting TLS")
                tls_start = time.time()
                context = ssl.create_default_context()
                server.starttls(context=context)
                print(f"TLS established in {time.time() - tls_start:.2f}s")

            # Login - this is the same for both connection types
            print("Authenticating with SMTP server")
            auth_start = time.time()
            server.login(smtp_username, smtp_password)
            auth_time = time.time() - auth_start
            print(f"Authentication successful in {auth_time:.2f}s")

            # Send email
            print(f"Sending email to {recipient}")
            send_start = time.time()
            server.send_message(message)
            send_time = time.time() - send_start
            print(f"Email sent in {send_time:.2f}s")

            total_time = time.time() - start_time
            print(f"Total email operation completed in {total_time:.2f}s")
            return True, "Email sent successfully"

        finally:
            # Restore original timeout
            socket.setdefaulttimeout(old_timeout)

            # Close the connection
            if server:
                try:
                    server.quit()
                    print("SMTP connection closed properly")
                except Exception as e:
                    print(f"Error closing SMTP connection: {e}")

    except socket.timeout as e:
        logger.error(f"SMTP timeout error: {e}")
        return False, f"SMTP timeout error: {e}"
    except socket.error as e:
        logger.error(f"Socket error: {e}")
        print(traceback.format_exc())
        print(f"sender_email: {sender_email}")
        print(f"smtp_server: {smtp_server}")
        print(f"smtp_port: {smtp_port}")
        print(f"smtp_port int: {int(smtp_port)}")
        print(f"smtp_username: {smtp_username}")
        print(f"smtp_password: {smtp_password}")
        return False, f"Socket error: {e}"
    except smtplib.SMTPServerDisconnected as e:
        logger.error(f"SMTP server disconnected: {e}")
        return False, f"SMTP server disconnected: {e}"
    except smtplib.SMTPAuthenticationError as e:
        logger.error(f"SMTP authentication error: {e}")
        return False, f"SMTP authentication error: {e}"
    except smtplib.SMTPException as e:
        logger.error(f"SMTP error: {e}")
        return False, f"SMTP error: {e}"
    except Exception as e:
        logger.error(f"Unexpected error sending email: {e}", exc_info=True)
        return False, f"Unexpected error: {e}"


def send_email(
    recipient,
    subject,
    body,
    html_body=None,
    sender_email=None,
    credentials=EMAIL_CREDENTIALS,
):
    """Backward-compatible synchronous email function"""
    company_name = os.environ.get("COMPANY_NAME", "Surfcity Nisaan")
    subject = f"{subject or ''} - {company_name}"
    success, message = send_email_with_timeout(
        recipient, subject, body, html_body, sender_email,credentials
    )
    if not success:
        logger.error(f"Failed to send email: {message}")
    return success


def send_welcome_email(recipient: str, name: str, password: str) -> bool:
    app_base_url = os.getenv("API_BASE_URL")
    """
    Send a welcome email with login credentials
    
    Args:
        recipient: Email address of the recipient
        name: Name of the recipient
        password: Generated password
        
    Returns:
        bool: True if email was sent successfully, False otherwise
    """
    subject = "Welcome to Dealerpulse Alpha - Your Login Credentials"

    body = f"""
Hello {name},

Welcome to Dealerpulse Alpha! Your account has been created.

Here are your login credentials:
Email: {recipient}
Password: {password}

You can login at: {app_base_url}
Please change your password after your first login for security reasons.

Best regards,
The Dealerpulse Alpha Team
"""

    html_body = f"""
<html> 
<body>
    <h2>Welcome to Dealerpulse Alpha!</h2>
    <p>Hello {name},</p>
    <p>Your account has been created. Here are your login credentials:</p>
    <p><strong>Email:</strong> {recipient}<br>
    <strong>Password:</strong> {password}</p>
    <p>You can login at: <a href="{app_base_url}">{app_base_url}</a></p>
    <p>Please change your password after your first login for security reasons.</p>
    <p>Best regards,<br>
    The Dealerpulse Alpha Team</p>
</body>
</html>
"""
    print(recipient, subject, body, html_body)
    return send_email(recipient, subject, body, html_body)
