#!/usr/bin/env python3
"""Rebuild the core figure-ready pressure and milestone CSVs from this source-data package.
Run from the root of FTaC_source_data_and_scripts_v01.
This script uses Python standard library only.
"""
import csv, re, math
from pathlib import Path
P0 = 101325.0
AHEAD_WINDOW_M = 0.010
ROOT = Path(__file__).resolve().parents[1]

def ffloat(x):
    try:
        if x is None or str(x).strip()=="": return None
        v=float(x)
        return None if math.isnan(v) else v
    except Exception:
        return None

def read_dicts(p):
    with open(p, newline='', errors='replace') as f:
        return list(csv.DictReader(f))

def write_csv(p, rows, fields):
    p.parent.mkdir(parents=True, exist_ok=True)
    with open(p, 'w', newline='') as f:
        w=csv.DictWriter(f, fieldnames=fields); w.writeheader()
        for r in rows: w.writerow({k:r.get(k,'') for k in fields})

def get_case(phi):
    case = {'phi0p9':'S09','phi1p0':'S10','phi1p1':'S11'}[phi]
    phi_val = {'phi0p9':'0.9','phi1p0':'1.0','phi1p1':'1.1'}[phi]
    return case, phi_val, ROOT/'02_raw_processed_cases'/phi

def find_master(case_dir, phi):
    return case_dir/'diagnostics'/f'master_precursors_{phi}.csv'

def find_centerline(case_dir, idx):
    pat = f'centerline_*_idx{idx:03d}_*.csv'
    matches = list((case_dir/'centerline').glob(pat))
    return matches[0] if matches else None

def load_line(path):
    vals=[]
    with open(path, newline='', errors='replace') as f:
        for r in csv.DictReader(f):
            x=ffloat(r.get('Points:0')); p=ffloat(r.get('p')); u=ffloat(r.get('U:0')); T=ffloat(r.get('T'))
            if x is not None: vals.append({'x':x,'p':p,'u':u,'T':T})
    return vals

def recompute_pressure(phi):
    case, phi_val, case_dir = get_case(phi)
    rows=[]
    for r in read_dicts(find_master(case_dir, phi)):
        idx=int(float(r['idx'])); t=ffloat(r.get('time')); xc=ffloat(r.get('x_center')); db=ffloat(r.get('Db_formal')); xtip=ffloat(r.get('x_tip'))
        peak=None; n=0
        line=find_centerline(case_dir, idx)
        if line and xc is not None:
            candidates=[v for v in load_line(line) if v['p'] is not None and xc <= v['x'] <= xc+AHEAD_WINDOW_M]
            n=len(candidates)
            if candidates: peak=max(candidates, key=lambda v:v['p'])
        dp=(peak['p']-P0)/1000 if peak else None
        rows.append({'case':case,'phi':phi_val,'idx':idx,'time_s':f'{t:.10g}' if t is not None else '',
                     'time_ms':f'{t*1000:.8g}' if t is not None else '', 'x_center_m':f'{xc:.8g}' if xc is not None else '',
                     'x_tip_m':f'{xtip:.8g}' if xtip is not None else '', 'Db_m':f'{db:.8g}' if db is not None else '',
                     'Db_mm':f'{db*1000:.8g}' if db is not None else '', 'p0_Pa':'101325',
                     'p_ahead_peak_Pa':f'{peak["p"]:.8g}' if peak else '', 'delta_p_ahead_kPa':f'{dp:.8g}' if dp is not None else '',
                     'x_p_peak_m':f'{peak["x"]:.8g}' if peak else '', 'n_centerline_points_in_ahead_window':n})
    return rows

def main():
    out = ROOT/'01_figure_ready_rebuilt'
    fields=['case','phi','idx','time_s','time_ms','x_center_m','x_tip_m','Db_m','Db_mm','p0_Pa','p_ahead_peak_Pa','delta_p_ahead_kPa','x_p_peak_m','n_centerline_points_in_ahead_window']
    allrows=[]
    for phi in ['phi0p9','phi1p0','phi1p1']:
        rows=recompute_pressure(phi); allrows += rows
        write_csv(out/f'rebuilt_ahead_overpressure_{phi}.csv', rows, fields)
    write_csv(out/'rebuilt_all_cases_ahead_overpressure.csv', allrows, fields)
    print(f'Wrote {len(allrows)} rows to {out}')
if __name__ == '__main__': main()
