"""Reinstall/retest public 0.1.25 assets, using original issue payloads unchanged."""
import json
import subprocess
import hashlib
from datetime import datetime
from pathlib import Path

LAB=Path(__file__).resolve().parents[1]
RELEASE=LAB/'releases/launcher-0.1.25'
EVIDENCE=LAB/'evidence/launcher-0.1.25-retest-2026-10-20'
OLD=LAB/'evidence/chapter-11-diagnostics-2026-10-20'
CLI=LAB/'tools/cli/Scripts/foggy-runtime.exe'
MODEL='ChinookInvoiceTimeQueryModel'
STAMP=datetime.now().astimezone().strftime('%Y%m%dT%H%M%S')
COMMANDS=[]
CASES=[]


def run(tag,args,required=True):
    command=[str(CLI),'--base-url','http://127.0.0.1:18068','--namespace','chinook',*map(str,args)]
    path=EVIDENCE/f'{STAMP}-{tag}.json'
    assert not path.exists(),path
    r=subprocess.run(command,capture_output=True,encoding='utf-8',timeout=60)
    path.write_text(r.stdout,encoding='utf-8')
    if r.stderr:path.with_suffix('.stderr.txt').write_text(r.stderr,encoding='utf-8')
    result=json.loads(r.stdout) if r.stdout.strip() else {}
    COMMANDS.append(dict(arguments=command,exitCode=r.returncode,response=str(path)))
    (EVIDENCE/f'{STAMP}-commands.json').write_text(json.dumps(COMMANDS,ensure_ascii=False,indent=2),encoding='utf-8')
    print(json.dumps(dict(step=tag,exitCode=r.returncode,success=result.get('success'),
        error=result.get('error'),rows=len(result.get('data',{}).get('items',[]))),ensure_ascii=False),flush=True)
    if required and (r.returncode or result.get('success') is not True):raise RuntimeError(f'{tag}: see {path}')
    return result,path,r.returncode


def probe(name,payload,source=None,explain=True):
    folder=EVIDENCE/'payloads';folder.mkdir(exist_ok=True)
    path=folder/f'{name}.json'
    if source:
        raw=Path(source).read_bytes();path.write_bytes(raw)
        assert hashlib.sha256(path.read_bytes()).digest()==hashlib.sha256(raw).digest()
    else:path.write_text(json.dumps(payload,ensure_ascii=False,indent=2),encoding='utf-8')
    v,vp,vc=run(name+'-validate',['query','validate',MODEL,'--payload',path],required=False)
    case=dict(name=name,payload=str(path),sourcePayload=str(source) if source else None,
        payloadSha256=hashlib.sha256(path.read_bytes()).hexdigest(),validation=str(vp),validationSuccess=v.get('success'),validationExitCode=vc)
    if v.get('success'):
        if explain:
            x,xp,xc=run(name+'-explain',['query','explain',MODEL,'--payload',path,'--depth','detailed','--include-sql','--include-physical-names'],required=False)
            case.update(explain=str(xp),explainSuccess=x.get('success'),explainExitCode=xc)
        r,rp,rc=run(name+'-execute',['query','execute',MODEL,'--payload',path],required=False)
        case.update(response=str(rp),executionSuccess=r.get('success'),executionExitCode=rc)
        if r.get('success'):
            print(json.dumps(dict(query=name,items=r.get('data',{}).get('items',[])[:2]),ensure_ascii=False),flush=True)
    else:case['executionSkipped']='Validation rejected payload; no invalid execution attempted.'
    CASES.append(case)
    (EVIDENCE/'query-manifest.json').write_text(json.dumps(dict(collectedAt=datetime.now().astimezone().isoformat(),
        runtimeUrl='http://127.0.0.1:18068',model=MODEL,cases=CASES),ensure_ascii=False,indent=2),encoding='utf-8')


def main():
    run('wait-ready',['wait-ready','--timeout-seconds','45','--interval-seconds','1'])
    caps,_,_=run('capabilities',['capabilities'])
    for c in ['datasources.add','datasources.bind','datasources.test','models.validate','models.describe','models.refresh','query.validate','query.explain','query.execute']:
        assert caps['data']['capabilities'][c]=='supported'
    run('datasource-add',['datasources','add','--name','chinook-sqlite','--type','sqlite','--jdbc-url','jdbc:sqlite:'+str(RELEASE/'data/Chinook.sqlite')])
    run('datasource-bind',['datasources','bind','--namespace','chinook','--data-source','chinook-sqlite'])
    run('datasource-test',['datasources','test','chinook-sqlite'])
    run('datasource-binding',['datasources','binding','--namespace','chinook'])
    run('datasource-diagnostics',['datasources','diagnostics'])
    run('tables-inspect',['tables','inspect','--data-source','chinook-sqlite','--table','Invoice','--include-indexes'])
    val,_,_=run('models-validate',['models','validate','--models-dir',RELEASE/'models'])
    assert val['data']['validFiles']==2 and val['data']['invalidFiles']==0
    run('bundle-add',['bundles','add','--name','chinook-time-retest-0125','--path',RELEASE/'models'])
    run('models-refresh',['models','refresh'])
    d,_,_=run('models-describe',['models','describe',MODEL])
    assert {'invoiceDate$id','invoiceDate$year','invoiceDate$month','invoiceDate$yearMonth','invoiceAmount','invoiceId'}<=d['data']['data']['fields'].keys()
    for name in ['01-monthly-control','02-lag-detail','03-lag-group-measure','04-lag-group-nested-sum',
        '05-lag-group-alias','06-rank-group','07-time-yoy','08-time-mom',
        '09-mom-extra-day-key-changes-grain','10-lag-separate-calculations','11-lag-compound-no-sum',
        '12-lag-control-without-explain','13-lag-including-prior-december']:
        p=OLD/'payloads'/f'{name}.json'
        probe(name,None,source=p,explain=name!='12-lag-control-without-explain')
    for name,comparison,start,end in [
        ('14-mom-cross-year','mom','2011-12-01','2012-02-01'),
        ('15-yoy-two-months','yoy','2012-10-01','2012-12-01'),
        ('16-yoy-no-prior-data','yoy','2009-01-01','2010-01-01'),
        ('17-mom-empty-period','mom','1990-01-01','1991-01-01')]:
        p=json.loads((OLD/'payloads/07-time-yoy.json').read_text(encoding='utf-8'))
        p['timeWindow'].update(comparison=comparison,value=[start,end])
        probe(name,p)


if __name__=='__main__':main()
