#!/usr/bin/env python3
# -*- coding: utf-8  -*-
import boto3
import os  
import logging
import datetime
from argparse import ArgumentParser

filename = os.path.basename(__file__)
logger = logging.getLogger(filename) 
logging.basicConfig()
logging.getLogger('boto3').setLevel(logging.ERROR)
logging.getLogger('boto3').propagate = False
logging.getLogger('botocore').setLevel(logging.ERROR)
logging.getLogger('botocore').propagate = False

parser = ArgumentParser("analyze-sqs-queue")
parser.add_argument(
    "-q",
    "--queue-name",
    dest="queue_name",
    help="Queue Name",
    required=False)
parser.add_argument(
    "-r",
    "--region",
    dest="region",
    help="Queue Region",
    required=False)
parser.add_argument(
    "-u",
    "--queue-url",
    dest="queue_url",
    help="Queue Url",
    required=False)
parser.add_argument(
    "-a",
    "--analyze-messages",
    dest="analyze",
    help="Analyze messages",
    action="store_true",
    required=False)
parser.add_argument(
    "-v",
    "--verbose",
    dest="verbose",
    help="Verbose output",
    action="store_true",
    required=False)
parser.add_argument(
    "-l",
    "--logger",
    dest="logger",
    help="Log level",
    choices=['DEBUG','INFO','WARNING','ERROR'],
    default='INFO',
    required=False)
args = parser.parse_args()

logger.setLevel(args.logger)

if args.queue_url and (args.region or args.queue_name):
    print('should be defined only "queue_url" or "queue_name"/"region" but not both')
    exit()
elif not (args.queue_url or (args.region and args.queue_name)):
    print('should be defined one of "queue_url" or "queue_name"/"region"')
    exit()

if args.queue_url:
    queue_url = args.queue_url
    queue_name = queue_url.split('/')[-1]
    if queue_url.startswith('https://sqs'):
        region_name = queue_url.split('.')[1]
    else:
        region_name = queue_url.split('https://')[1].split('.')[0]
    sqs = boto3.client('sqs', region_name=region_name)
else:
    queue_name = args.queue_name
    region_name = args.region
    sqs = boto3.client('sqs', region_name=region_name)
    queue_url = sqs.get_queue_url(QueueName=queue_name)['QueueUrl']

def yes_no(answer):
    yes = set(['yes','y', 'ye', ''])
    no = set(['no','n'])
     
    while True:
        choice = input(answer).lower()
        if choice in yes:
           return True
        elif choice in no:
           return False
        else:
           print("Please respond with 'yes' or 'no'\n")

def main():
    print("Attributes of Queue: ", queue_url)
    queue_attributes = sqs.get_queue_attributes(
        QueueUrl=queue_url,
        AttributeNames=['All']
    )['Attributes']
    for attribute, val in queue_attributes.items():
        print('\t', attribute, ': ', val)

    if args.analyze:
        if int(queue_attributes['ApproximateNumberOfMessages']) == 0:
            print('Zero messages in the queue, skip analizing')
            exit()
        print("Analize Queue (last and first message):", queue_url)
        if int(queue_attributes['ApproximateNumberOfMessages']) > 1000:
            if not yes_no('Number of messages in the queue {}, do you want to get all these messages?'.format(queue_attributes['ApproximateNumberOfMessages'])):
                exit()
        for msg in analyze_queue(queue_url):
            print('\t SenderId:', msg['Attributes']['SenderId'])
            print('\t ApproximateReceiveCount:', msg['Attributes']['ApproximateReceiveCount'])
            print('\t ApproximateFirstReceiveTimestamp:', datetime.datetime.fromtimestamp(int(msg['Attributes']['ApproximateFirstReceiveTimestamp'])/1000))
            print('\t SentTimestamp:', datetime.datetime.fromtimestamp(int(msg['Attributes']['SentTimestamp'])/1000))
            print('\t MessageAttributes:')
            if msg.get('MessageAttributes'):
                for attribute, val in msg['MessageAttributes'].items():
                    print('\t\t', attribute, ': ', val['StringValue'])
            if args.verbose:
                print('\t Message Content:', msg['Body'])
            print('\t ------------------------------------------')

# Analyze queue content
# read all available messages,
# collect and display some information about them
# - number of read messages,
# the latest and oldest message (its id and timestamp,
# number of attempts to process it),
# and others that you think may be helpful in the analysis,
#  you don't need to display the content of the latest and oldest message by default,
# maybe use another option to enable this;

def analyze_queue(queue_url):
    logger.debug("Analyze queue: ", queue_url)
    all_messages = []
    messages = sqs.receive_message(
        QueueUrl=queue_url,
        AttributeNames=['All'],
        MaxNumberOfMessages=10,
        VisibilityTimeout=10,
    )
    while messages.get('Messages'):
        all_messages += messages['Messages']
        messages = sqs.receive_message(
            QueueUrl=queue_url,
            AttributeNames=['All'],
            MessageAttributeNames=['All'],
            MaxNumberOfMessages=10,
            VisibilityTimeout=10,
        )
    first = None
    last = None
    for message in all_messages:
        if not first:first = message
        if not last:last = message
        msg_timestamp = int(message['Attributes']['SentTimestamp'])/1000
        if datetime.datetime.fromtimestamp(msg_timestamp) < datetime.datetime.fromtimestamp(int(first['Attributes']['SentTimestamp'])/1000):
            first = message
        if datetime.datetime.fromtimestamp(msg_timestamp) > datetime.datetime.fromtimestamp(int(last['Attributes']['SentTimestamp'])/1000):
            last = message
    print('\t\t\t last:', last)
    return first,last

if __name__ == '__main__':
    main()
