"""One-time migration through an SSM tunnel; all generated files stay outside Git."""
import argparse
import hashlib
import json
import os
from pathlib import Path
import secrets
import subprocess
import psycopg
from psycopg.conninfo import make_conninfo


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--outputs', required=True)
    parser.add_argument('--source', required=True, help='enterprise-orders source directory')
    parser.add_argument('--secure-dir', required=True, help='NEW directory outside the repository')
    parser.add_argument('--ca', required=True)
    args = parser.parse_args()
    cfg = json.loads(Path(args.outputs).read_text())
    source = Path(args.source).resolve()
    ca = str(Path(args.ca).resolve())
    root = Path(args.secure_dir).resolve()
    # Refuse a directory inside any Git checkout to avoid archiving credentials.
    if any((p / '.git').exists() for p in [root, *root.parents]):
        raise SystemExit('secure-dir must be outside all Git worktrees')
    aws = ['aws', '--region', cfg['region']]
    master = json.loads(subprocess.check_output(aws + ['secretsmanager', 'get-secret-value',
        '--secret-id', cfg['db_master_secret'], '--query', 'SecretString', '--output', 'text']))
    dsn = make_conninfo(host=cfg['db_host'], hostaddr='127.0.0.1', port=15432, dbname='orders',
                       user=master['username'], password=master['password'], sslmode='verify-full', sslrootcert=ca)
    with psycopg.connect(dsn, connect_timeout=10) as db:
        if db.execute("SELECT to_regclass('public.schema_migrations')").fetchone()[0]:
            raise SystemExit('Database already initialized; do not regenerate credentials')
    root.mkdir(mode=0o700, parents=False, exist_ok=False)

    def write(name, body):
        fd = os.open(root / name, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600)
        with os.fdopen(fd, 'w') as f:
            f.write(body)

    passwords = {f'{kind}_{site}': secrets.token_hex(24) for kind in ('api', 'worker') for site in ('a', 'b')}
    tokens = {tenant: secrets.token_urlsafe(32) for tenant in ('release-verification', 'other-tenant')}
    write('token', tokens['release-verification'])
    write('other-token', tokens['other-tenant'])
    write('recovery-passwords.json', json.dumps(passwords))
    payload = {'auth': {hashlib.sha256(token.encode()).hexdigest(): tenant for tenant, token in tokens.items()}}
    for kind in ('api', 'worker'):
        payload[kind + '_dsn'] = make_conninfo(host=cfg['db_host'], port=5432, dbname='orders',
            user=f'orders_{kind}_a', password=passwords[kind + '_a'], sslmode='verify-full', sslrootcert='/run/secrets/ca.pem')
    write('runtime.json', json.dumps(payload))
    env = {**os.environ, 'DATABASE_URL': dsn, **{k.upper() + '_PASSWORD': v for k, v in passwords.items()}}
    subprocess.run([os.sys.executable, 'migrate.py'], cwd=source, env=env, check=True)
    write('migration-complete', 'ok\n')
    subprocess.run(aws + ['secretsmanager', 'put-secret-value', '--secret-id', cfg['runtime_secret'],
        '--secret-string', 'file://' + str(root / 'runtime.json')], stdout=subprocess.DEVNULL, check=True)
    print('Migration and runtime secret complete; client tokens remain in secure-dir')


if __name__ == '__main__':
    main()
