
import boto3
import argparse
import json
import datetime
import time

def get_r53_hosted_zone_id(domain_name, r53_client):
    """
    Finds the Hosted Zone ID for a given domain name in Route 53.
    """
    paginator = r53_client.get_paginator('list_hosted_zones')
    for page in paginator.paginate():
        for zone in page['HostedZones']:
            # Match exact domain or subdomain
            if domain_name.endswith(zone['Name'][:-1]) or domain_name == zone['Name'][:-1]:
                return zone['Id'].split('/')[-1]
    return None

def create_r53_cname_record(hosted_zone_id, record_name, record_value, r53_client):
    """
    Creates a CNAME record in Route 53 for ACM validation.
    """
    try:
        r53_client.change_resource_record_sets(
            HostedZoneId=hosted_zone_id,
            ChangeBatch={
                'Changes': [
                    {
                        'Action': 'UPSERT',
                        'ResourceRecordSet': {
                            'Name': record_name,
                            'Type': 'CNAME',
                            'TTL': 60,
                            'ResourceRecords': [
                                {'Value': record_value}
                            ]
                        }
                    },
                ]
            }
        )
        print(f"      Successfully created/updated CNAME record for {record_name} in Hosted Zone {hosted_zone_id}.")
        return True
    except Exception as e:
        print(f"      Error creating CNAME record for {record_name}: {e}")
        return False

def monitor_acm_certificates(
    region_name: str = 'us-east-1',
    create_r53_records: bool = False
):
    """
    Monitors ACM certificates and reports their status.
    Optionally creates Route 53 validation records for pending DNS-validated certificates.
    """
    acm_client = boto3.client('acm', region_name=region_name)
    r53_client = boto3.client('route53', region_name=region_name) if create_r53_records else None

    print(f"Starting ACM certificate monitoring in region {region_name}...
")

    # ==========================================================================
    # STEP 1: List all ACM certificates in the specified region.
    # ==========================================================================
    print(">>> Step 1: Listing all ACM certificates...")
    certificates = []
    paginator = acm_client.get_paginator('list_certificates')
    for page in paginator.paginate(CertificateStatuses=['PENDING_VALIDATION', 'ISSUED', 'EXPIRED', 'FAILED', 'INACTIVE']):
        certificates.extend(page['CertificateSummaryList'])

    if not certificates:
        print("   No ACM certificates found in this region.")
        return
    print(f"   Found {len(certificates)} certificates.
")

    # ==========================================================================
    # STEP 2: Describe each certificate and report its status.
    # ==========================================================================
    print(">>> Step 2: Analyzing each certificate...")
    for cert_summary in certificates:
        cert_arn = cert_summary['CertificateArn']
        domain_name = cert_summary['DomainName']
        status = cert_summary['Status']
        not_after = cert_summary.get('NotAfter')

        print(f"  Certificate: {domain_name}")
        print(f"    ARN: {cert_arn}")
        print(f"    Status: {status}")
        if not_after:
            print(f"    Expires: {not_after}")
            days_to_expire = (not_after - datetime.datetime.now(datetime.timezone.utc)).days
            print(f"    Days to expire: {days_to_expire}")
            if days_to_expire < 30 and status == 'ISSUED':
                print("    WARNING: Certificate expiring soon! Check renewal status.")

        # ==========================================================================
        # STEP 3: Handle PENDING_VALIDATION certificates.
        # If `create_r53_records` is True, attempt to create DNS records.
        # ==========================================================================
        if status == 'PENDING_VALIDATION':
            print("    ACTION REQUIRED: Certificate is PENDING_VALIDATION.")
            cert_details = acm_client.describe_certificate(CertificateArn=cert_arn)['Certificate']
            
            # Check if it's a DNS validated certificate
            if cert_details.get('DomainValidationOptions'):
                for validation_option in cert_details['DomainValidationOptions']:
                    if validation_option['ValidationMethod'] == 'DNS':
                        resource_record = validation_option.get('ResourceRecord')
                        if resource_record:
                            record_name = resource_record['Name']
                            record_value = resource_record['Value']
                            print(f"      DNS Validation Record needed: CNAME {record_name} -> {record_value}")

                            if create_r53_records and r53_client:
                                hosted_zone_id = get_r53_hosted_zone_id(validation_option['DomainName'], r53_client)
                                if hosted_zone_id:
                                    print(f"      Found Route 53 Hosted Zone ID: {hosted_zone_id} for {validation_option['DomainName']}")
                                    create_r53_cname_record(hosted_zone_id, record_name, record_value, r53_client)
                                else:
                                    print(f"      WARNING: Could not find Route 53 Hosted Zone for {validation_option['DomainName']}. Manual DNS update required.")
                            else:
                                print("      To automate, run with --create-r53-records if domain is in Route 53.")
                        else:
                            print("      No DNS validation record found in details. Check certificate request.")
            else:
                print("      Validation method is not DNS. Manual email validation likely required.")

        elif status == 'FAILED':
            print("    CRITICAL: Certificate FAILED validation or renewal. Manual intervention required.")
        elif status == 'EXPIRED':
            print("    CRITICAL: Certificate EXPIRED. Immediate action required.")
        
        print("--------------------------------------------------")

    print("\nACM certificate monitoring completed.")

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Monitor AWS ACM certificates and assist with renewal.")
    parser.add_argument("--region", default="us-east-1", help="AWS region to scan (default: us-east-1).")
    parser.add_argument("--create-r53-records", action="store_true", help="If set, attempts to create CNAME validation records in Route 53 for pending DNS-validated certificates.")

    args = parser.parse_args()

    monitor_acm_certificates(
        region_name=args.region,
        create_r53_records=args.create_r53_records
    )
