#!/usr/bin/env python

import os, sys
import subprocess, shlex
from datetime import date, time, datetime
from dateutil.relativedelta import relativedelta

from app import app, db
from flask_script import Manager, Shell, Command
from flask_migrate import Migrate, MigrateCommand

def make_shell_context():
    from app.models import User, Role, Permission, Deployment
    return dict(app=app,
                db=db, 
                User=User, 
                Role=Role, 
                Permission=Permission, 
                Deployment=Deployment)

migrate = Migrate(app, db)

manager = Manager(app)
manager.add_command('shell', Shell(make_context=make_shell_context))
manager.add_command('db', MigrateCommand)

@manager.command
def deploy():
    """Run deployment tasks."""
    from flask_migrate import upgrade
    from app.models import Role, User

    # migrate database to latest revision
    upgrade()

    # create user roles
    Role.insert_roles()

@manager.command
def autoremove():
    from app.models import User, Deployment
    today = datetime.utcnow()
    print('\nScan for unprotected deployments, lower their days left by 1 and autodelete them if expired. Script Started at {}'.format(today))
    drafts = Deployment.query.filter_by(deleted=False).filter_by(protected=False).all()
    for draft in drafts:
        daysleft = draft.daysleft
        daysleft -= 1
        draft.daysleft = daysleft
        print('Draft {} will be autoremoved after {} days.'.format(draft.machine_alias, daysleft))
        db.session.commit()

@manager.command
def autodisable():
    from app.models import User, Deployment, Service, Domain
    from sqlalchemy import and_, or_, not_
    today = datetime.utcnow()
    print('\nScan for active expired items and set them as inactive. Script started at {}'.format(today))
    dep_c = 0
    srv_c = 0
    dom_c = 0
    deployments = Deployment.query.filter_by(deleted=False).filter_by(enabled=True).filter_by(protected=True).all()
    for deploy in deployments:
        #print('Found {}.'.format(str(deploy.machine_alias)))
        lastcharge = deploy.date_last_charge
        expiry = lastcharge + relativedelta(lastcharge, months=+(deploy.period))
        if today > expiry:
            print('Deployment "' + deploy.machine_alias + '" is past expiration date and will be marked INACTIVE. Last charged: ' + lastcharge.strftime('%c') + ' expiry date: ' + expiry.strftime('%c'))
            deploy.warning = False
            deploy.enabled = False
            deploy.daysleft = 0
            db.session.commit()
        else:
            dep_c += 1
    services_ena = Service.query.filter_by(deleted=False).filter_by(enabled=True).all()
    for service in services_ena:
        lastcharge = service.date_last_charge
        expiry = lastcharge + relativedelta(lastcharge, months=+(service.period))
        if today > expiry:
            print('Service "' + service.description + '" is past expiration date and will be marked INACTIVE. Last charged: ' + lastcharge.strftime('%c') + ' expiry date: ' + expiry.strftime('%c'))
            service.warning = False
            service.enabled = False
            service.daysleft = 0
            db.session.commit()
        else:
            srv_c += 1
    domains_ena = Domain.query.filter_by(deleted=False).filter_by(enabled=True).all()
    for domain in domains_ena:
        expiry = domain.date_expire
        if today > expiry:
            print('Domain "' + domain.fqdn + '" is past expiration date and will be marked as INACTIVE. Last charged: ' + lastcharge.strftime('%c') + ' expiry date: ' + expiry.strftime('%c'))
            domain.warning = False
            domain.enabled = False
            domain.daysleft = 0
            db.session.commmit()
        else:
            dom_c += 1
    print('Total Active Deployments: {}, Services: {}, Domains: {}'.format(dep_c, srv_c, dom_c))

@manager.command
def autowarn():
    from app.models import User, Deployment, Service, Domain, Transaction
    today = datetime.utcnow()
    print('\nScan for items that will expire soon and enable the warning flag. Script started at {}'.format(today))
    deployments_ena = Deployment.query.filter_by(deleted=False).filter_by(enabled=True).filter_by(protected=True).all()
    for deploy in deployments_ena:
        lastcharge = deploy.date_last_charge
        expiry = lastcharge + relativedelta(lastcharge, months=+(deploy.period))
        daysleft = expiry - today
        deploy.daysleft = daysleft.days + 1
        db.session.commit()
        warndays = deploy.period * 5
        if daysleft.days < warndays:
            print('Deployment "' + deploy.machine_alias + '" is ' + str(daysleft.days) + ' days until expiration. Last charged: ' + lastcharge.strftime('%c') + ' expiry date: ' + expiry.strftime('%c'))
            deploy.warning = True
            db.session.commit()

    services_ena = Service.query.filter_by(deleted=False).filter_by(enabled=True).all()
    for service in services_ena:
        lastcharge = service.date_last_charge
        expiry = lastcharge + relativedelta(lastcharge, months=+(service.period))
        daysleft = expiry - today
        service.daysleft = daysleft.days + 1
        db.session.commit()
        warndays = service.period * 5
        if daysleft.days < warndays:
            print('Service "' + service.description + '" is ' + str(daysleft.days) + ' days until expiration. Last charged: ' + lastcharge.strftime('%c') + ' expiry date: ' + expiry.strftime('%c'))
            service.warning = True
            db.session.commit()
            
    domains_ena = Domain.query.filter_by(deleted=False).filter_by(enabled=True).all()
    for domain in domains_ena:
        expiry = domain.date_expire
        daysleft = expiry - today
        domain.daysleft = daysleft.days + 1
        db.session.commit()
        warndays = domain.period * 5
        if daysleft.days < warndays:
            print('Domain "' + domain.fqdn + '" is ' + str(daysleft.days)+ ' days until expiration. Expiry date: ' + expiry.strftime('%c'))
            domain.warning = True
            db.session.commit()

@manager.command
def runserver():
    print('Starting Flask...')
    app.run()

if __name__ == '__main__':
    manager.run()

