#!/usr/bin/env python3
"""Reproduce from original cb-allotment paths and frozen local market caches.
Raw market data and provider credentials are not included in code downloads.
"""
import argparse
from pathlib import Path
import hashlib,json,subprocess,sys

def main():
    parser=argparse.ArgumentParser(description=__doc__)
    parser.add_argument('--test-only',action='store_true')
    parser.add_argument('--allow-changed-inputs',action='store_true',help='Treat changed/missing caches as a new experiment')
    args=parser.parse_args()
    root=Path(__file__).resolve().parents[4]
    if not (root/'research/etf_qdii_extension.py').is_file():parser.error('Run at the original path inside cb-allotment with local market caches.')
    if args.test_only:
        for pattern in ['test_etf_practical_optimization.py','test_etf_return20_study.py','test_etf_qdii_extension.py']:
            subprocess.run([sys.executable,'-m','unittest','discover','-s','research','-p',pattern,'-v'],cwd=root,check=True)
    else:
        if not args.allow_changed_inputs:
            manifest=json.loads(Path(__file__).with_name('input_manifest.json').read_text())
            changed=[]
            for name,record in manifest.items():
                file=root/name;expected=record['sha256'] if isinstance(record,dict) else record
                if not file.is_file() or hashlib.sha256(file.read_bytes()).hexdigest()!=expected:changed.append(name)
            if changed:parser.error('Frozen inputs changed/missing. Restore caches or use --allow-changed-inputs for a new experiment: '+', '.join(changed[:10]))
        subprocess.run([sys.executable,'research/etf_qdii_extension.py'],cwd=root,check=True)
        subprocess.run([sys.executable,'research/build_etf_qdii_report.py'],cwd=root,check=True)

if __name__=='__main__':main()
