#!/usr/bin/env python3
from pathlib import Path
import os, subprocess, sys, json, uuid, hashlib, shutil

root=Path(__file__).resolve().parents[2]
status_path=root/'learner/evidence/runtime-status.json'

def sha(path): return hashlib.sha256(path.read_bytes()).hexdigest()
def save(obj): status_path.write_text(json.dumps(obj,indent=2)+"\n")

def base_status():
    return {
      'schema':'DAT007_RUNTIME_STATUS_v2','status':'NOT_RUN',
      'drizzle_status':'NOT_RUN','postgresql_status':'NOT_RUN',
      'actual_drizzle_runtime_evidence_claimed':False,
      'actual_postgresql_runtime_evidence_claimed':False,
      'fabricated_runtime_evidence':False,'generated_schema':None,
      'postgresql_version':None,'negative_probe_sqlstates':{},
      'provenance_sha256':{},'cleanup_status':'NOT_APPLICABLE'
    }

obj=base_status()
if os.environ.get('DAT007_LOCAL_DISPOSABLE')!='YES':
    obj['status']='NOT_RUN_CONFIRMATION_REQUIRED'; save(obj); print(obj['status']); sys.exit(2)
if not shutil.which('psql'):
    obj['status']='NOT_RUN_MISSING_REAL_POSTGRESQL_RUNTIME'; save(obj); print(obj['status']); sys.exit(3)
dsn=os.environ.get('DAT007_DATABASE_URL','').strip()
if not dsn:
    obj['status']='NOT_RUN_MISSING_DATABASE_URL'; save(obj); print(obj['status']); sys.exit(2)

schema='dat007_'+uuid.uuid4().hex[:12]
if not schema.startswith('dat007_') or not schema[7:].isalnum():
    raise RuntimeError('generated schema guard failed')
psql=['psql',dsn,'-X','-v','ON_ERROR_STOP=1','-v','VERBOSITY=verbose','-qAt']

def run_sql(sql,check=True,timeout=20):
    p=subprocess.run(psql+['-c',sql],capture_output=True,text=True,timeout=timeout)
    if check and p.returncode!=0: raise RuntimeError(p.stderr.strip())
    return p

def sqlstate(stderr):
    import re
    m=re.search(r'ERROR:\s+([0-9A-Z]{5}):',stderr or '')
    return m.group(1) if m else None

created=False
try:
    run_sql(f'CREATE SCHEMA "{schema}";'); created=True
    prefix=f'SET search_path TO "{schema}"; '
    version=run_sql('SHOW server_version;').stdout.strip()
    for f in ['schema_baseline.sql','seed.sql']:
        run_sql(prefix+(root/'learner/sql'/f).read_text())

    # Drift must be demonstrated before any migration modifies the database.
    drift_before=run_sql(prefix+(root/'learner/sql/drift_probe.sql').read_text()).stdout.strip().lower()
    if drift_before not in {'f','false'}:
        raise RuntimeError('drift precondition failed: baseline database unexpectedly has handle')

    collision=run_sql(prefix+(root/'learner/sql/normalize_collision_probe.sql').read_text()).stdout.strip()
    if 'sara-noor' not in collision.lower() or not any(tok in collision for tok in ['|2','\t2',',2']):
        raise RuntimeError('collision probe did not prove the seeded duplicate candidate')

    generated=(root/'learner/drizzle/0001_generated_candidate.sql')
    bad_generated=run_sql(prefix+generated.read_text(),check=False)
    generated_state=sqlstate(bad_generated.stderr)
    if bad_generated.returncode==0 or generated_state!='23502':
        raise RuntimeError(f'generated review fixture did not fail with expected 23502; observed={generated_state}')

    naive=(root/'learner/sql/naive_transition_collision.sql')
    bad_collision=run_sql(prefix+naive.read_text(),check=False)
    collision_state=sqlstate(bad_collision.stderr)
    if bad_collision.returncode==0 or collision_state!='23505':
        raise RuntimeError(f'naive transition did not fail with expected 23505; observed={collision_state}')

    provenance_files=[
      'learner/src/schema.target.ts',
      'learner/drizzle/0001_generated_candidate.sql',
      'learner/sql/naive_transition_collision.sql',
      'learner/sql/normalize_collision_probe.sql',
      'learner/sql/drift_probe.sql',
    ]
    obj.update({
      'status':'RUNTIME_NEGATIVE_PROBES_VERIFIED',
      'postgresql_status':'PASS_NEGATIVE_PROBES_REAL_POSTGRESQL',
      'actual_postgresql_runtime_evidence_claimed':True,
      'actual_drizzle_runtime_evidence_claimed':False,
      'generated_schema':schema,
      'postgresql_version':version,
      'drift_before_apply':drift_before,
      'collision_probe':collision,
      'negative_probe_sqlstates':{'generated_required_column_precondition':generated_state,'naive_normalization_collision':collision_state},
      'provenance_sha256':{f:sha(root/f) for f in provenance_files},
      'cleanup_status':'PENDING'
    })
    save(obj)
finally:
    if created:
        # Cleanup is bound to the exact generated namespace only. Never substitute a literal shared schema.
        cp=subprocess.run(psql+['-c',f'DROP SCHEMA IF EXISTS "{schema}" CASCADE;'],capture_output=True,text=True,timeout=20)
        obj['cleanup_status']='PASS_EXACT_GENERATED_SCHEMA' if cp.returncode==0 else 'FAIL_CLEANUP'
        save(obj)

if obj.get('cleanup_status')!='PASS_EXACT_GENERATED_SCHEMA':
    print(json.dumps(obj,indent=2)); sys.exit(1)
print(json.dumps(obj,indent=2))
