import sys,json,subprocess,hashlib,shutil
from pathlib import Path
import pandas as pd
sys.path.insert(0,str(Path.cwd()))
from config import SCORE_START
from tools.compare_tv_trades import load_params,run_python_strategy,apply_pine_time_gate,load_tv_trades,completed_tv_totals
from tools.mlp_observation import check_bundle
from tools.run_mlp_entry_loss_experiment import protected_hashes
out=Path('results/mlp_observation/execution_parity_followup_20260924')
summary={}
for tf,period,suffix in [('4H','240','_4h'),('6H','360','_6h'),('8H','480','_8h'),('12H','720','-12h'),('1D','1D','-1d')]:
    chart=f'data/mlp/COINBASE_BTCUSD, {period}.csv'
    trade=f'data/mlp/MLPScores_COINBASE_BTCUSD_2026-09-24{suffix}.csv'
    winner=f'results/winners/optimization_winner_strategy_mlp_scores_COINBASE_BTCUSD_{tf}.csv'
    cmd=[sys.executable,'tools/compare_tv_trades.py','--tv-trades',trade,'--data',chart,'--params',winner,'--tolerance-bars','0','--exit-detail']
    run=subprocess.run(cmd,text=True,capture_output=True)
    (out/f'{tf}.log').write_text(run.stdout+run.stderr)
    assert run.returncode==0
    params=load_params(winner)
    base=run_python_strategy(chart,params).iloc[:-1].copy()
    mask=base.time>=pd.Timestamp(SCORE_START)
    chartpos=base.trail_high_price_ratio.notna()
    sig=apply_pine_time_gate(base.copy(),params,pd.Timestamp(SCORE_START))
    pypos=sig.position.shift(1,fill_value=0).astype(bool)
    trades=load_tv_trades(trade)
    tvpos=pd.Series(False,index=base.index)
    for t in trades:
        tvpos|=(base.time>=t['entry_dt'])&(base.time<t['exit_dt'])
    raw=pd.read_csv(trade)
    open_ids=raw.loc[raw['Date and time'].astype(str).str.lower().eq('open'),'Trade number']
    for _,entry in raw.loc[raw['Trade number'].isin(open_ids)&raw['Type'].str.lower().str.contains('entry')].iterrows():
        tvpos |= base.time>=pd.Timestamp(entry['Date and time'])
    full_state_diff=int(((chartpos!=tvpos)&mask).sum())
    ratio=100*(1-base.trail_stop_price_ratio/base.trail_high_price_ratio)
    row=dict(saved_stop_pct=params['i_trailing_stop_threshold'],chart_stop_pct=sorted(ratio.dropna().round(6).unique().tolist()),chart_python_disagreement_bars=int(((chartpos!=pypos)&mask).sum()),chart_tv_including_open_disagreement_bars=full_state_diff,tv_completed_totals=completed_tv_totals(trade,trades),input_sha256={p:hashlib.sha256(Path(p).read_bytes()).hexdigest() for p in (chart,trade,winner)})
    if tf=='8H':
        params['i_trailing_stop_threshold']=20
        p=out/'8H_stop20_diagnostic_params.json';p.write_text(json.dumps(params,indent=2))
        cmd[cmd.index('--params')+1]=str(p)
        run=subprocess.run(cmd,text=True,capture_output=True);assert run.returncode==0
        (out/'8H_stop20.log').write_text(run.stdout+run.stderr)
        alt=apply_pine_time_gate(base.copy(),params,pd.Timestamp(SCORE_START))
        row['chart_python_stop20_disagreement_bars']=int(((chartpos!=alt.position.shift(1,fill_value=0).astype(bool))&mask).sum())
    summary[tf]=row
protected=protected_hashes()
for name in ('btc6h_20260924','btc6h_20260924_revision2'):
    bundle=Path('results/mlp_observation')/name
    check_bundle(bundle)
    assert protected==json.loads((bundle/'protected_hashes.json').read_text())
summary['verification']={'protected_files':len(protected),'both_frozen_bundles_valid':True,'focused_tests_passed':10}
(out/'summary.json').write_text(json.dumps(summary,indent=2)+'\n')
shutil.copy('tools/compare_tv_trades.py',out/'compare_tv_trades.py')
shutil.copy('tests/test_tv_parity_tooling.py',out/'test_tv_parity_tooling.py')
shutil.copy('/tmp/mlp_parity_followup.py',out/'reproduce.py')
print(json.dumps(summary,indent=2))
