import boto3
from botocore.exceptions import ClientError
import time
import json

# A script to demonstrate basic SNS topic operations (create, subscribe email, publish, unsubscribe, delete)
# using Boto3.

# --- Configuration ---
REGION = "us-east-1"
TOPIC_NAME = "MyBoto3SNSTopic"
EMAIL_ADDRESS = "your-email@example.com" # !!! IMPORTANT: Replace with your actual email address !!!

sns_client = boto3.client('sns', region_name=REGION)

def create_sns_topic():
    """Creates an SNS topic."""
    print(f"--- Creating SNS Topic: {TOPIC_NAME} ---")
    try:
        response = sns_client.create_topic(Name=TOPIC_NAME)
        topic_arn = response['TopicArn']
        print(f"Topic created with ARN: {topic_arn}")
        return topic_arn
    except ClientError as e:
        if e.response['Error']['Code'] == 'TopicLimitExceededException':
            print(f"Topic limit exceeded. Please delete existing topics or request a limit increase.")
        else:
            raise e

def subscribe_email(topic_arn):
    """Subscribes an email address to the SNS topic."""
    print(f"\n--- Subscribing email address: {EMAIL_ADDRESS} to the topic ---")
    response = sns_client.subscribe(
        TopicArn=topic_arn,
        Protocol='email',
        Endpoint=EMAIL_ADDRESS
    )
    subscription_arn = response['SubscriptionArn']
    print(f"Subscription initiated. Check your email ({EMAIL_ADDRESS}) for a confirmation link.")
    print("You MUST click the confirmation link in the email for the subscription to become active.")
    input("Press Enter after you have confirmed the subscription in your email...")

    # Verify subscription status
    print("\n--- Verifying subscription status ---")
    while True:
        try:
            attrs = sns_client.get_subscription_attributes(SubscriptionArn=subscription_arn)['Attributes']
            if attrs['PendingConfirmation'] == 'false':
                print("Subscription confirmed successfully.")
                return subscription_arn
            else:
                print("Subscription is still pending confirmation. Waiting 5 seconds...")
                time.sleep(5)
        except ClientError as e:
            if e.response['Error']['Code'] == 'NotFoundException':
                print("Subscription not found, likely deleted before confirmation. Exiting.")
                return None
            else:
                raise e

def publish_message(topic_arn):
    """Publishes a message to the SNS topic."""
    print("\n--- Publishing a message to the topic ---")
    message_subject = "Boto3 SNS Test Message"
    message_body = "This is a test message sent from Boto3 to your email."
    sns_client.publish(
        TopicArn=topic_arn,
        Subject=message_subject,
        Message=message_body
    )
    print("Message published. Check your email for the notification.")

def unsubscribe_email(subscription_arn):
    """Unsubscribes the email address."""
    print("\n--- Unsubscribing email address ---")
    sns_client.unsubscribe(SubscriptionArn=subscription_arn)
    print("Email address unsubscribed.")

def delete_sns_topic(topic_arn):
    """Deletes the SNS topic."""
    print(f"\n--- Deleting SNS Topic: {TOPIC_NAME} ---")
    sns_client.delete_topic(TopicArn=topic_arn)
    print(f"Topic {TOPIC_NAME} deleted successfully.")

def main():
    topic_arn = None
    subscription_arn = None
    try:
        topic_arn = create_sns_topic()
        if topic_arn:
            subscription_arn = subscribe_email(topic_arn)
            if subscription_arn:
                publish_message(topic_arn)
                unsubscribe_email(subscription_arn)
            else:
                print("Subscription was not confirmed, skipping publish and unsubscribe.")
        
        if topic_arn:
            delete_sns_topic(topic_arn)
        
        print("\n--- SNS publish/subscribe demonstration complete ---")

    except ClientError as e:
        print(f"An AWS client error occurred: {e}")
    except Exception as e:
        print(f"An unexpected error occurred: {e}")

if __name__ == "__main__":
    main()
