#!/usr/bin/env python3
"""Run explicit repository quality checks, collecting failures without a false green."""
import argparse, datetime, fcntl, json, os, pathlib, signal, subprocess, sys, uuid

def execute(argv, cwd, log, timeout):
    with log.open('w') as output:
        try:
            process = subprocess.Popen(argv, cwd=cwd, stdout=output, stderr=subprocess.STDOUT,
                                       env={**os.environ, 'CI': 'true'}, start_new_session=True)
            try:
                return process.wait(timeout=timeout)
            except subprocess.TimeoutExpired:
                os.killpg(process.pid, signal.SIGKILL)
                process.wait()
                output.write('\nTIMEOUT\n')
                return 124
        except OSError as error:
            output.write(str(error))
            return 127

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--plan', action='store_true')
    args = parser.parse_args()
    root = pathlib.Path(__file__).resolve().parents[1]
    config = json.loads((root / 'quality-gate.json').read_text())
    if args.plan:
        print(json.dumps(config, indent=2)); return 0
    state = root / '.quality'; state.mkdir(exist_ok=True)
    with (state / 'gate.lock').open('w') as lock:
        try: fcntl.flock(lock, fcntl.LOCK_EX | fcntl.LOCK_NB)
        except BlockingIOError: print('Quality gate already running', file=sys.stderr); return 75
        run = state / 'reports' / uuid.uuid4().hex; run.mkdir(parents=True)
        os.environ['AISTHETIX_QUALITY_RUN_DIR'] = str(run)
        sha = subprocess.check_output(['git','rev-parse','HEAD'],cwd=root,text=True).strip()
        dirty_before = subprocess.check_output(['git','status','--porcelain'],cwd=root,text=True)
        results = []
        for index, step in enumerate(config['steps']):
            log = run / f'{index:02}-{step["name"]}.log'
            rc = execute(step['argv'], root / step.get('cwd','.'), log, step.get('timeout',900))
            results.append({'name':step['name'],'exit_code':rc,'log':str(log.relative_to(root))})
            print(f'{step["name"]}: {"PASS" if rc == 0 else "FAIL"}', flush=True)
        dirty_after = subprocess.check_output(['git','status','--porcelain'],cwd=root,text=True)
        end_sha = subprocess.check_output(['git','rev-parse','HEAD'],cwd=root,text=True).strip()
        passed = bool(results) and all(r['exit_code']==0 for r in results) and not dirty_before and not dirty_after and sha == end_sha
        report = {'schema':1,'repository':config['repository'],'sha':sha,'finished_at':datetime.datetime.now(datetime.timezone.utc).isoformat(),'passed':passed,'clean_before':not bool(dirty_before),'clean_after':not bool(dirty_after),'same_commit':sha==end_sha,'steps':results}
        (run/'report.json').write_text(json.dumps(report,indent=2)+'\n')
        (state/'latest.json').write_text(json.dumps(report,indent=2)+'\n')
        print(f'Report: {run}/report.json')
        if dirty_before or dirty_after: print('QA requires a clean committed worktree; generated tracked changes must be resolved.')
        return 0 if passed else 1
if __name__ == '__main__': sys.exit(main())
