#!/opt/dosis2/bin/python3-venv

import os
import sys
import socket
import psycopg2
import argparse
import boto3
import configparser
import logging
import logging.config
import xml.etree.ElementTree as ET
import pprint

pp = pprint.PrettyPrinter(indent=4)


logging.config.dictConfig({
    'disable_existing_loggers': False,
    'version': 1,
    'formatters': {
        'standard': {
            'format': "[%(asctime)s] %(levelname)s [%(name)s:%(lineno)s] %(message)s",
        },
    },
    'handlers': {
        'console_handler': {
            'class': 'logging.StreamHandler',
            'level': 'INFO',
            'stream': 'ext://sys.stdout',
            'formatter': 'standard'
        },
    },
    'loggers': {
        'console_logger': {
            'handlers': ['console_handler'],
            'level': 'DEBUG',
            'propogate': 0
        }
    },
    'root': {
        'level': 'INFO',
        'handlers': ['console_handler']
    }
})

logger = logging.getLogger(__name__)

DOSIS_CONF = '/opt/dosis2/etc/custom/dosisConfig.xml'

def get_args():
    parser = argparse.ArgumentParser(
        prog='get-aws-backup',
        usage='%(prog)s [options]',
        description='Gets backup for DOSIS Tower/SiteServer from AWS'
    )
    parser.add_argument('-d', '--day', required=True, help='DOW (day of week) of backup to retrieve e.g. Monday, Tuesday, Wednesday, etc.')
    return parser.parse_args()


class GetAwsBackup(object):
    def __init__(self, dosis_config_path, dow):
        self.dosis_config_path = dosis_config_path
        self.dow = dow
        self.dafe_tag = ''
        self.db_ip = ''
        self.cust_num = '' #CUST prefix is upper
        self.server_name = '' #SS prefix is uppper
        self.dafe_type = ''
        self.backup_name = ''


    def print_all(self):
        print(('dosis_config_path %s ' % self.dosis_config_path))
        print(('dow %s ' % self.dow))
        print(('dafe_tag %s ' % self.dafe_tag))
        print(('db_ip %s ' % self.db_ip))
        print(('cust_num %s ' % self.cust_num))
        print(('server_name %s ' % self.server_name))
        print(('dafe_type %s ' % self.dafe_type))
        print(('backup_name %s ' % self.backup_name))


    def does_file_exist(self, path):
        return os.path.exists(path)


    def safe_mkdir(self, path):
        if self.does_file_exist(path):
            return True
        else:
            os.mkdir(path)
            return True


    def parse_dosis_config(self, attrib):
        tree = ET.parse(self.dosis_config_path)
        root = tree.getroot()
        return root.find('.//*[@name="{attrib}"]/value'.format(attrib=attrib)).text


    def set_dafe_tag(self):
        self.dafe_tag = socket.gethostname()


    def set_db_ip(self):
        self.db_ip = self.parse_dosis_config('DBServer')


    def set_dafe_type(self):
        self.dafe_type = self.parse_dosis_config('DafeType')


    def set_cust_num(self):
        try:
            conn = psycopg2.connect("dbname='dosis2' user='dsuper' host='%s' password='1$Dosis'" % self.db_ip)
            cur = conn.cursor()
            cur.execute("""
            SELECT site.site_settings.value as site_setting_value
            FROM site.site_settings
            LEFT JOIN site.site_setting_types ON (site.site_settings.setting_type_id = site.site_setting_types.id)
            WHERE site.site_setting_types.tag = 'CUSTOMER_NUMBER';
            """)
            self.cust_num = 'CUST%s' % cur.fetchone()[0].upper()
        except psycopg2.OperationalError as err:
            logger.error(err)


    def set_backup_name(self):
        if self.dafe_type == 'SITE_SERVER':
            self.backup_name = 'SYSTEM'
        else:
            self.backup_name = self.dafe_tag


    # this is the machine responsible for backing up
    def set_server_name(self):
        # if it's a standalone the database ip should be localhost.
        if self.db_ip == '127.0.0.1' and self.dafe_type != 'SITE_SERVER':
            self.server_name = self.dafe_tag
        else:
            self.server_name = self.cust_num.replace('CUST', 'SS')


    def get_backup(self):
        remote = 'sites/{cust_num}/{server_name}/{dow}/{backup_name}'.format(
            cust_num=self.cust_num,
            server_name=self.server_name,
            dow=self.dow,
            backup_name=self.backup_name
        )
        logger.info('Pulling backup from: %s' % remote)
        local = '/tmp/{backup_name}_{dow}_Backup'.format(backup_name=self.backup_name, dow=self.dow)
        logger.info('Saving to: %s' % local)
        self.safe_mkdir(local)
        config = configparser.ConfigParser()
        config.read('/opt/dosis2/.aws/credentials')
        aws_access_key_id = config['default']['aws_access_key_id']
        aws_secret_access_key =  config['default']['aws_secret_access_key']
        s3 = boto3.client('s3', aws_access_key_id=aws_access_key_id, aws_secret_access_key=aws_secret_access_key)
        paginator = s3.get_paginator("list_objects_v2")
        for page in paginator.paginate(Bucket="dosis-site-backups", Prefix=remote):
            for content in page['Contents']:
                s3.download_file(Bucket='dosis-site-backups', Key=content['Key'], Filename='{local}/{filename}'.format(local=local, filename=os.path.basename(content['Key'])))


    def run(self):
        self.set_dafe_tag()
        self.set_db_ip()
        self.set_dafe_type()
        self.set_cust_num()
        self.set_backup_name()
        self.set_server_name()
        self.print_all()
        self.get_backup()


# get DOW as cli argument

if __name__ == '__main__':
    valid_dows = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
    args = get_args()
    dow = args.day.title()

    if dow not in valid_dows:
        sys.exit('%s is not a valid dow' % dow)

    gab = GetAwsBackup(DOSIS_CONF, dow)
    gab.run()



