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

# A script to create a public hosted zone and an A record in Route 53 using Boto3.

# --- Configuration ---
REGION = "us-east-1"
DOMAIN_NAME = "example.com" # !!! IMPORTANT: Replace with a domain you own or a test domain !!!
SUBDOMAIN_NAME = f"www.{DOMAIN_NAME}"
RECORD_IP = "192.0.2.1" # A sample IP address

route53_client = boto3.client('route53', region_name=REGION)

def create_hosted_zone():
    """Creates a public hosted zone."""
    print(f"--- Creating Public Hosted Zone for {DOMAIN_NAME} ---")
    try:
        response = route53_client.create_hosted_zone(
            Name=DOMAIN_NAME,
            CallerReference=str(uuid.uuid4()), # Unique string for idempotency
            HostedZoneConfig={'Comment': 'My Boto3 Test Hosted Zone'}
        )
        hosted_zone_id = response['HostedZone']['Id'].split('/')[-1]
        print(f"Hosted Zone created with ID: {hosted_zone_id}")
        return hosted_zone_id
    except ClientError as e:
        if e.response['Error']['Code'] == 'HostedZoneAlreadyExists':
            print(f"Hosted Zone for '{DOMAIN_NAME}' already exists. Skipping creation.")
            response = route53_client.list_hosted_zones_by_name(DNSName=DOMAIN_NAME)
            return response['HostedZones'][0]['Id'].split('/')[-1]
        else:
            print(f"Error creating hosted zone: {e}")
            raise

def create_a_record(hosted_zone_id):
    """Creates an A record within the hosted zone."""
    print(f"\n--- Creating A record for {SUBDOMAIN_NAME} pointing to {RECORD_IP} ---")
    try:
        route53_client.change_resource_record_sets(
            HostedZoneId=hosted_zone_id,
            ChangeBatch={
                'Changes': [
                    {
                        'Action': 'CREATE',
                        'ResourceRecordSet': {
                            'Name': SUBDOMAIN_NAME,
                            'Type': 'A',
                            'TTL': 300,
                            'ResourceRecords': [{'Value': RECORD_IP}]
                        }
                    }
                ]
            }
        )
        print("A record created.")
    except ClientError as e:
        print(f"Error creating A record: {e}")
        raise

def get_ns_records(hosted_zone_id):
    """Retrieves and prints the Name Servers for the hosted zone."""
    print(f"\n--- Name Servers for your Hosted Zone (update these with your domain registrar) ---")
    try:
        response = route53_client.get_hosted_zone(Id=hosted_zone_id)
        for ns in response['DelegationSet']['NameServers']:
            print(f"- {ns}")
    except ClientError as e:
        print(f"Error getting NS records: {e}")
        raise

def cleanup_resources(hosted_zone_id):
    """Cleans up all created resources."""
    print(f"\n--- Cleaning up resources ---")

    # Delete A Record
    print(f"Deleting A record '{SUBDOMAIN_NAME}'...")
    try:
        route53_client.change_resource_record_sets(
            HostedZoneId=hosted_zone_id,
            ChangeBatch={
                'Changes': [
                    {
                        'Action': 'DELETE',
                        'ResourceRecordSet': {
                            'Name': SUBDOMAIN_NAME,
                            'Type': 'A',
                            'TTL': 300,
                            'ResourceRecords': [{'Value': RECORD_IP}]
                        }
                    }
                ]
            }
        )
        print("A record deleted.")
    except ClientError as e:
        if e.response['Error']['Code'] == 'InvalidChangeBatch':
            print(f"A record '{SUBDOMAIN_NAME}' not found, skipping deletion.")
        else:
            print(f"Error deleting A record: {e}")

    # Delete Hosted Zone
    print(f"Deleting Hosted Zone '{DOMAIN_NAME}'...")
    try:
        route53_client.delete_hosted_zone(Id=hosted_zone_id)
        print("Hosted Zone deleted.")
    except ClientError as e:
        if e.response['Error']['Code'] == 'NoSuchHostedZone':
            print(f"Hosted Zone '{DOMAIN_NAME}' not found, skipping deletion.")
        else:
            print(f"Error deleting hosted zone: {e}")

def main():
    hosted_zone_id = None
    try:
        hosted_zone_id = create_hosted_zone()
        create_a_record(hosted_zone_id)
        get_ns_records(hosted_zone_id)

        print("\n--- Route 53 Hosted Zone setup complete! ---")
        print(f"Hosted Zone ID: {hosted_zone_id}")
        print(f"A Record: {SUBDOMAIN_NAME} -> {RECORD_IP}")

        input("Press Enter to delete the A record and Hosted Zone...")

    except ClientError as e:
        print(f"An AWS client error occurred: {e}")
    except Exception as e:
        print(f"An unexpected error occurred: {e}")
    finally:
        if hosted_zone_id:
            cleanup_resources(hosted_zone_id)
        print("\n--- Route 53 demonstration and cleanup complete ---")

if __name__ == "__main__":
    main()
