"""CTCLR-09: editable policy -> reviewed persistent policy, without Web enrolment."""
import copy
import json
from pathlib import Path
import time

import field_profiles as fp
from data_console import ask, say
from data_safety import atomic, lock
from data_host import Host
from storage_policy import NAME, validate


def defaults(host):
    e=host.env
    cap=int(e.get('CONTEXTRA_ARTIFACT_CAP_BYTES',100*1024**3))
    minimum=int(e.get('CONTEXTRA_ARTIFACT_MIN_FREE_BYTES',50*1024**3))
    t=json.loads((host.paths()['training']/'settings.json').read_text())
    return validate(dict(version=1,
        artifact=dict(max_bytes=cap,target_bytes=cap*9//10,min_free_bytes=minimum,auto_cleanup=e.get('CONTEXTRA_ARTIFACT_RETENTION_ENABLED','false')=='true'),
        training=dict(max_bytes=t['max_bytes'],target_bytes=t['max_bytes']*9//10,min_free_bytes=t['min_free_bytes'],auto_cleanup=True)))


def view(host):
    source=fp.SETUP/'storage.json';applied=host.paths()['artifact']/NAME
    effective=validate(json.loads(applied.read_text())) if applied.exists() else defaults(host)
    configured=validate(fp.read_json(source)) if source.exists() else copy.deepcopy(effective)
    return source,applied,configured,effective


def main(args):
    import argparse
    p=argparse.ArgumentParser(description='ct storage [status|edit|apply]')
    p.add_argument('action',nargs='?',default='status',choices=('status','edit','apply'))
    a=p.parse_args(args);host=Host()
    source,applied,configured,effective=view(host)
    say('일반 편집 원본: '+str(source),'Editable source: '+str(source))
    say('실제 적용 위치: '+str(applied),'Applied policy: '+str(applied))
    for kind in ('artifact','training'):
        print(kind,'configured=',configured[kind],'applied=',effective[kind])
    say('단위는 10진 바이트입니다. 실행 중 Runtime 유효값은 별도이며 적용 후 다음 기동에 일치합니다.',
        'Units: decimal bytes. Applied file is not proof of current running values; next startup consumes it.')
    if a.action=='status':
        say('편집: ct storage edit 또는 위 원본 파일 / 적용: ct storage apply',
            'Edit: ct storage edit or the source file / apply: ct storage apply')
        return
    if a.action=='edit':
        for kind in ('artifact','training'):
            for key in ('max_bytes','target_bytes','min_free_bytes','auto_cleanup'):
                old=configured[kind][key]
                raw=ask(f'{kind}.{key} [{old}; Enter=현재값 유지]: ',f'{kind}.{key} [{old}; Enter=keep]: ')
                if raw:
                    if key=='auto_cleanup':
                        if raw.lower() not in ('true','false'):raise ValueError('Use true or false')
                        configured[kind][key]=raw.lower()=='true'
                    else:configured[kind][key]=int(raw)
        fp.atomic(source,validate(configured),user=True)
        say('저장만 완료. 자동 정리 Off도 공간 제한은 유지합니다. 다음: ct storage apply',
            'Saved only. Cleanup Off keeps space/admission protection. Next: ct storage apply')
        return
    if host.writers():raise ValueError('STOP_ANALYSIS_BEFORE_POLICY_APPLY')
    labels=json.loads(__import__('compose_backend').execute(['docker','image','inspect',host.image]))[0]['Config'].get('Labels') or {}
    if labels.get('contextra.storage-policy')!='1':raise ValueError('STORAGE_RUNTIME_PATCH_REQUIRED')
    say('상한을 낮추면 다음 기동 후 자동 정리나 저장 제한이 발생할 수 있습니다. Web 로그인은 하지 않습니다.',
        'Lower caps may trigger cleanup or admission rejection after start. No Web login.')
    if ask('보관 정책만 적용하려면 APPLY 입력: ','Type APPLY to apply storage policy only: ')!='APPLY':return
    with lock(fp.STATE/'data-maintenance.lock'):
        if host.writers():raise ValueError('WRITER_RESTARTED')
        name='storage-'+str(time.time_ns());record=fp.STATE/'storage-changes'/name
        atomic(record/'before.json',effective)
        atomic(record/'after.json',configured)
        atomic(applied,configured)
        atomic(record/'result.json',dict(applied=True,runtime_started=False))
    say('정책 적용 완료. 서비스는 정지 유지. 다음 ct start에서 사용합니다.',
        'Policy applied. Services remain stopped. Used by the next ct start.')
