"""Independent-phase conditional correction, distinct from paired-field binning."""
from __future__ import annotations
import argparse,json
from pathlib import Path
import numpy as np
import scipy.signal
from .artifacts import atomic_save_npz,atomic_write_json


def _phase(x): return np.mod(np.angle(scipy.signal.hilbert(np.asarray(x,float)-np.mean(x))),2*np.pi)

def run(run_dir:Path,*,x0:int,x1:int,y0:int,y1:int,stride:int,bins:int=12):
 out=run_dir/"aligned/phase_conditioned_independent.npz"
 if out.exists(): raise FileExistsError(out)
 with np.load(run_dir/"controlled/telemetry.npz") as t: pc=_phase(t["sensors"][:,3])
 with np.load(run_dir/"time_paired_baseline/telemetry.npz") as t: pb=_phase(t["sensors"][:,3])
 edges=np.linspace(0,2*np.pi,bins+1); products=[]; counts_c=None;counts_b=None
 for key in ("ux","uy"):
  means=[]
  for branch,phase in (("controlled",pc),("time_paired_baseline",pb)):
   with np.load(run_dir/branch/"fields.npz") as f:
    idx=f["control_indices"]; labels=np.minimum(np.digitize(phase[np.minimum(idx,len(phase)-1)],edges)-1,bins-1)
    field=f[key][:,x0:x1:stride,y0:y1:stride]
    conditional=np.full((bins,field.shape[1],field.shape[2]),np.nan,np.float32); counts=[]
    for i in range(bins):
     selected=labels==i; counts.append(int(selected.sum()))
     if selected.any(): conditional[i]=field[selected].mean(axis=0)
   means.append(conditional)
   if branch=="controlled": counts_c=counts
   else: counts_b=counts
  products.append((means[0]-means[1]).reshape(bins,-1))
 correction=np.hstack(products).astype(np.float32)
 atomic_save_npz(out,correction=correction,phase_centers=(edges[:-1]+edges[1:])/2,
                 controlled_counts=np.asarray(counts_c),baseline_counts=np.asarray(counts_b))
 report={"definition":"E[q_ctl|phi_ctl]-E[q_blk|phi_blk]","bins":bins,"features":correction.shape[1],
         "controlled_min_count":min(counts_c),"baseline_min_count":min(counts_b),
         "finite":bool(np.isfinite(correction).all()),"rms":float(np.sqrt(np.mean(correction**2)))}
 atomic_write_json(run_dir/"aligned/phase_conditioned_report.json",report);return report

def main(argv=None):
 p=argparse.ArgumentParser();p.add_argument("run_dir",type=Path);p.add_argument("--x0",type=int,required=True);p.add_argument("--x1",type=int,required=True);p.add_argument("--y0",type=int,required=True);p.add_argument("--y1",type=int,required=True);p.add_argument("--stride",type=int,default=4);p.add_argument("--bins",type=int,default=12);a=p.parse_args(argv);print(json.dumps(run(a.run_dir,x0=a.x0,x1=a.x1,y0=a.y0,y1=a.y1,stride=a.stride,bins=a.bins),indent=2));return 0
if __name__=="__main__":raise SystemExit(main())
