#!/usr/bin/env python3
"""Dune Echo Tours management commands.

    python manage.py init-db              create/upgrade the database and load the initial content (once)
    python manage.py migrate              apply pending schema migrations only
    python manage.py create-admin EMAIL   create an administrator (password asked interactively)
    python manage.py backup               write a backup .zip to instance/backups/
    python manage.py restore FILE.zip     restore a backup (a safety backup is taken first)
    python manage.py run [--port 5000]    development server
    python manage.py serve [--port 8000]  production server (waitress)
"""
import getpass
import os
import sys

from app import create_app
from app.backup import create_backup, restore_backup
from app.db import connect, migrate


def main(argv):
    if not argv or argv[0] in ('-h', '--help', 'help'):
        print(__doc__)
        return 0
    cmd, args = argv[0], argv[1:]
    app = create_app()
    cfg = app.config

    def port(default):
        return int(args[args.index('--port') + 1]) if '--port' in args else default

    if cmd == 'init-db':
        from app.seed import seed
        con = connect(cfg['DATABASE'])
        print('migrations applied:', migrate(con) or 'none')
        print('initial content loaded' if seed(con) else 'database already has content: nothing overwritten')
        con.close()
    elif cmd == 'migrate':
        con = connect(cfg['DATABASE'])
        print('migrations applied:', migrate(con) or 'none')
        con.close()
    elif cmd == 'create-admin':
        if not args:
            print('usage: python manage.py create-admin EMAIL')
            return 2
        email = args[0].strip().lower()
        pw = os.environ.get('ADMIN_PASSWORD') or getpass.getpass('Password (12+ characters): ')
        if len(pw) < 12:
            print('Password too short: use at least 12 characters.')
            return 2
        if not os.environ.get('ADMIN_PASSWORD') and getpass.getpass('Repeat password: ') != pw:
            print('Passwords do not match.')
            return 2
        from werkzeug.security import generate_password_hash
        con = connect(cfg['DATABASE'])
        migrate(con)
        if con.execute('SELECT 1 FROM users WHERE email=?', (email,)).fetchone():
            con.execute("UPDATE users SET pw_hash=?, role='admin', active=1 WHERE email=?", (generate_password_hash(pw), email))
            print('Existing user updated: administrator, new password set.')
        else:
            con.execute("INSERT INTO users(email, pw_hash, role) VALUES (?,?, 'admin')", (email, generate_password_hash(pw)))
            print('Administrator created:', email)
        con.commit()
        con.close()
    elif cmd == 'backup':
        print(create_backup(cfg['DATABASE'], cfg['UPLOAD_DIR'], cfg['BACKUP_DIR'], note='manage.py'))
    elif cmd == 'restore':
        if not args or not os.path.exists(args[0]):
            print('usage: python manage.py restore path/to/backup.zip')
            return 2
        manifest, safety = restore_backup(args[0], cfg['DATABASE'], cfg['UPLOAD_DIR'], cfg['BACKUP_DIR'])
        print('restored backup created', manifest.get('created'), '| safety copy:', safety)
    elif cmd == 'run':
        app.run(host='127.0.0.1', port=port(5000), debug=cfg['ENV'] != 'production')
    elif cmd == 'serve':
        from waitress import serve
        print(f"serving on http://0.0.0.0:{port(8000)}  (SITE_URL={cfg['SITE_URL']})")
        serve(app, host='0.0.0.0', port=port(8000), threads=8)
    else:
        print(__doc__)
        return 2
    return 0


if __name__ == '__main__':
    sys.exit(main(sys.argv[1:]))
