"""Reviewed maintenance bundle CLI. Transport does not grant deployment authority."""
import argparse
from pathlib import Path
import time

import field_profiles as fp
import server_context as server
from field_ui import input, print


def compatibility():
    import compose_backend
    a=compose_backend.active();doc=fp.read_json(compose_backend.current_path(),8*1024**2)
    return {'maintenance_api':1,'backend':server.CURRENT['backend'],
            'images':{k:v['image'] for k,v in doc['services'].items()}}


def root_for(kind):
    return Path(__file__).parent if kind=='TOOLS' else server.path('source','/workspace/contextra/source')


def update_inventory(root,changed):
    path=Path(root)/'installed-files.json'
    inventory=fp.read_json(path,1048576)
    from deployment_kit.core import sha256
    for name,expected in inventory.items():
        if name not in changed and sha256(fp.safe_path(Path(root)/name))!=expected:
            raise ValueError('Unrelated tool changes preserved; inventory not renewed')
    for name in changed:
        p=fp.safe_path(Path(root)/name)
        if p.exists():inventory[name]=sha256(p)
        else:inventory.pop(name,None)
    fp.atomic(path,inventory,mode=0o644)


def main(argv):
    from deployment_kit import maintenance_bundle as bundle
    parser=argparse.ArgumentParser(description=__doc__)
    parser.add_argument('action',choices=('create','verify','apply','restore'))
    parser.add_argument('path',type=Path)
    parser.add_argument('--sha256')
    parser.add_argument('--spec',type=Path)
    args=parser.parse_args(argv)
    if args.action=='create':
        spec=fp.read_json(args.spec)
        print(bundle.create(spec['source'],spec['baseline'],args.path,kind=spec['kind'],version=spec['version'],
            compatibility=compatibility(),paths=spec['paths'],changes=spec['changes']))
        return
    if args.action=='restore':
        path=fp.safe_path(args.path)
        if path.parent!=fp.STATE/'patches':raise ValueError('Use an owned patch journal')
        record=fp.read_json(path,64*1024**2)
        if record['root'] not in (str(root_for('TOOLS')),str(root_for('APP_SOURCE'))):raise ValueError('Unknown rollback root')
        if input('Restore only these files, no Runtime/DB/auth rollback? RESTORE: ')=='RESTORE':
            bundle.restore(record['root'],path,fp.atomic)
            if record['root']==str(root_for('TOOLS')):update_inventory(record['root'],record['files'])
            print('Restored. No service action.')
        return
    if not args.sha256:raise ValueError('Use separately approved --sha256; checksum is not publisher authentication')
    m,payload=bundle.verify(args.path,args.sha256)
    if m['compatibility']!=compatibility():raise ValueError('Server/image compatibility differs; review bundle instead of bypass')
    root=root_for(m['kind']);rows=bundle.plan(m,root)
    print('Kind:',m['kind'],'effect:',m['effect'],'target:',root)
    for row in rows:print(row['path'],row['state'])
    if args.action=='apply':
        if input('Apply reviewed code only; services unchanged? APPLY: ')!='APPLY':return
        journal=fp.STATE/'patches'/(args.sha256+'.json')
        bundle.apply(m,payload,root,journal,fp.atomic)
        if m['kind']=='TOOLS':update_inventory(root,m['files'])
        print('Applied. Resume uses same command; restore journal:',journal)
