#!/usr/bin/env python3
"""Test script to diagnose SMTP connection issues.

This script tests SMTP connectivity with different configurations to help
identify whether the issue is with credentials, network, ports, or TLS settings.
"""

import smtplib
import ssl
import sys
from datetime import datetime
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

# Load configuration from config.yaml
try:
    from alpine_bits_python.config_loader import load_config

    print("Loading configuration from config.yaml...")
    config = load_config()
    email_config = config.get("email", {})
    smtp_config = email_config.get("smtp", {})

    SMTP_HOST = smtp_config.get("host", "smtp.titan.email")
    SMTP_PORT = smtp_config.get("port", 465)
    SMTP_USERNAME = smtp_config.get("username", "")
    SMTP_PASSWORD = smtp_config.get("password", "")
    USE_TLS = smtp_config.get("use_tls", False)
    USE_SSL = smtp_config.get("use_ssl", True)
    FROM_ADDRESS = email_config.get("from_address", "info@99tales.net")
    FROM_NAME = email_config.get("from_name", "AlpineBits Monitor")

    # Get test recipient
    monitoring_config = email_config.get("monitoring", {})
    daily_report = monitoring_config.get("daily_report", {})
    recipients = daily_report.get("recipients", [])
    TEST_RECIPIENT = recipients[0] if recipients else "jonas@vaius.ai"

    print(f"✓ Configuration loaded successfully")
    print(f"  SMTP Host: {SMTP_HOST}")
    print(f"  SMTP Port: {SMTP_PORT}")
    print(f"  Username: {SMTP_USERNAME}")
    print(f"  Password: {'***' if SMTP_PASSWORD else '(not set)'}")
    print(f"  Use SSL: {USE_SSL}")
    print(f"  Use TLS: {USE_TLS}")
    print(f"  From: {FROM_ADDRESS}")
    print(f"  Test Recipient: {TEST_RECIPIENT}")
    print()

except Exception as e:
    print(f"✗ Failed to load configuration: {e}")
    print("Using default values for testing...")
    SMTP_HOST = "smtp.titan.email"
    SMTP_PORT = 465
    SMTP_USERNAME = input("Enter SMTP username: ")
    SMTP_PASSWORD = input("Enter SMTP password: ")
    USE_TLS = False
    USE_SSL = True
    FROM_ADDRESS = "info@99tales.net"
    FROM_NAME = "AlpineBits Monitor"
    TEST_RECIPIENT = input("Enter test recipient email: ")
    print()


def create_test_message(subject: str) -> MIMEMultipart:
    """Create a test email message."""
    msg = MIMEMultipart("alternative")
    msg["Subject"] = subject
    msg["From"] = f"{FROM_NAME} <{FROM_ADDRESS}>"
    msg["To"] = TEST_RECIPIENT
    msg["Date"] = datetime.now().strftime("%a, %d %b %Y %H:%M:%S %z")

    body = f"""SMTP Connection Test - {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}

This is a test email to verify SMTP connectivity.

Configuration:
- SMTP Host: {SMTP_HOST}
- SMTP Port: {SMTP_PORT}
- Use SSL: {USE_SSL}
- Use TLS: {USE_TLS}

If you received this email, the SMTP configuration is working correctly!
"""

    msg.attach(MIMEText(body, "plain"))
    return msg


def test_smtp_connection(host: str, port: int, timeout: int = 10) -> bool:
    """Test basic TCP connection to SMTP server."""
    import socket

    print(f"Test 1: Testing TCP connection to {host}:{port}...")
    try:
        sock = socket.create_connection((host, port), timeout=timeout)
        sock.close()
        print(f"✓ TCP connection successful to {host}:{port}")
        return True
    except socket.timeout:
        print(f"✗ Connection timed out after {timeout} seconds")
        print(f"  This suggests a network/firewall issue blocking access to {host}:{port}")
        return False
    except socket.error as e:
        print(f"✗ Connection failed: {e}")
        return False


def test_smtp_ssl(host: str, port: int, username: str, password: str, timeout: int = 30) -> bool:
    """Test SMTP connection with SSL."""
    print(f"\nTest 2: Testing SMTP with SSL (port {port})...")
    try:
        context = ssl.create_default_context()
        with smtplib.SMTP_SSL(host, port, timeout=timeout, context=context) as server:
            print(f"✓ Connected to SMTP server with SSL")

            # Try to get server info
            server.ehlo()
            print(f"✓ EHLO successful")

            # Try authentication if credentials provided
            if username and password:
                print(f"  Attempting authentication as: {username}")
                server.login(username, password)
                print(f"✓ Authentication successful")
            else:
                print(f"⚠ No credentials provided, skipping authentication")

            return True

    except smtplib.SMTPAuthenticationError as e:
        print(f"✗ Authentication failed: {e}")
        print(f"  Check your username and password")
        return False
    except socket.timeout:
        print(f"✗ Connection timed out after {timeout} seconds")
        print(f"  Try increasing timeout or check network/firewall")
        return False
    except Exception as e:
        print(f"✗ SMTP SSL failed: {e}")
        return False


def test_smtp_tls(host: str, port: int, username: str, password: str, timeout: int = 30) -> bool:
    """Test SMTP connection with STARTTLS."""
    print(f"\nTest 3: Testing SMTP with STARTTLS (port {port})...")
    try:
        with smtplib.SMTP(host, port, timeout=timeout) as server:
            print(f"✓ Connected to SMTP server")

            # Try STARTTLS
            context = ssl.create_default_context()
            server.starttls(context=context)
            print(f"✓ STARTTLS successful")

            # Try authentication if credentials provided
            if username and password:
                print(f"  Attempting authentication as: {username}")
                server.login(username, password)
                print(f"✓ Authentication successful")
            else:
                print(f"⚠ No credentials provided, skipping authentication")

            return True

    except smtplib.SMTPAuthenticationError as e:
        print(f"✗ Authentication failed: {e}")
        return False
    except socket.timeout:
        print(f"✗ Connection timed out after {timeout} seconds")
        return False
    except Exception as e:
        print(f"✗ SMTP TLS failed: {e}")
        return False


def send_test_email(host: str, port: int, username: str, password: str,
                   use_ssl: bool, use_tls: bool, timeout: int = 30) -> bool:
    """Send an actual test email."""
    print(f"\nTest 4: Sending test email...")
    try:
        msg = create_test_message("SMTP Test Email - AlpineBits")

        if use_ssl:
            context = ssl.create_default_context()
            with smtplib.SMTP_SSL(host, port, timeout=timeout, context=context) as server:
                if username and password:
                    server.login(username, password)
                server.send_message(msg, FROM_ADDRESS, [TEST_RECIPIENT])

        else:
            with smtplib.SMTP(host, port, timeout=timeout) as server:
                if use_tls:
                    context = ssl.create_default_context()
                    server.starttls(context=context)

                if username and password:
                    server.login(username, password)

                server.send_message(msg, FROM_ADDRESS, [TEST_RECIPIENT])

        print(f"✓ Test email sent successfully to {TEST_RECIPIENT}")
        print(f"  Check your inbox!")
        return True

    except Exception as e:
        print(f"✗ Failed to send email: {e}")
        return False


def main():
    """Run all SMTP tests."""
    print("=" * 70)
    print("SMTP Connection Test Script")
    print("=" * 70)
    print()

    # Test 1: Basic TCP connection
    tcp_ok = test_smtp_connection(SMTP_HOST, SMTP_PORT, timeout=10)

    if not tcp_ok:
        print("\n" + "=" * 70)
        print("DIAGNOSIS: Cannot establish TCP connection to SMTP server")
        print("=" * 70)
        print("\nPossible causes:")
        print("1. The SMTP server is down or unreachable")
        print("2. A firewall is blocking the connection")
        print("3. The host or port is incorrect")
        print("4. Network connectivity issues from your container/server")
        print("\nTroubleshooting:")
        print(f"- Verify the server is correct: {SMTP_HOST}")
        print(f"- Verify the port is correct: {SMTP_PORT}")
        print("- Check if your container/server has outbound internet access")
        print("- Try from a different network or machine")
        print(f"- Use telnet/nc to test: telnet {SMTP_HOST} {SMTP_PORT}")
        return 1

    # Test 2 & 3: Try both SSL and TLS
    ssl_ok = False
    tls_ok = False

    if USE_SSL:
        ssl_ok = test_smtp_ssl(SMTP_HOST, SMTP_PORT, SMTP_USERNAME, SMTP_PASSWORD, timeout=30)

    # Also try common alternative ports
    if not ssl_ok and SMTP_PORT == 465:
        print("\n⚠ Port 465 failed, trying port 587 with STARTTLS...")
        tls_ok = test_smtp_tls(SMTP_HOST, 587, SMTP_USERNAME, SMTP_PASSWORD, timeout=30)

    if USE_TLS:
        tls_ok = test_smtp_tls(SMTP_HOST, SMTP_PORT, SMTP_USERNAME, SMTP_PASSWORD, timeout=30)

    if not ssl_ok and not tls_ok:
        print("\n" + "=" * 70)
        print("DIAGNOSIS: Cannot authenticate or establish secure connection")
        print("=" * 70)
        print("\nPossible causes:")
        print("1. Wrong username or password")
        print("2. Wrong port for the encryption method")
        print("3. SSL/TLS version mismatch")
        print("\nTroubleshooting:")
        print("- Verify your credentials are correct")
        print("- Port 465 typically uses SSL")
        print("- Port 587 typically uses STARTTLS")
        print("- Port 25 is usually unencrypted (not recommended)")
        return 1

    # Test 4: Send actual email
    send_ok = send_test_email(
        SMTP_HOST, SMTP_PORT, SMTP_USERNAME, SMTP_PASSWORD,
        USE_SSL, USE_TLS, timeout=30
    )

    print("\n" + "=" * 70)
    if send_ok:
        print("✓ ALL TESTS PASSED!")
        print("=" * 70)
        print("\nYour SMTP configuration is working correctly.")
        print(f"Check {TEST_RECIPIENT} for the test email.")
    else:
        print("⚠ PARTIAL SUCCESS")
        print("=" * 70)
        print("\nConnection and authentication work, but email sending failed.")
        print("This might be a temporary issue. Try again.")

    return 0


if __name__ == "__main__":
    try:
        sys.exit(main())
    except KeyboardInterrupt:
        print("\n\nTest cancelled by user")
        sys.exit(1)
