"""DEPRECATED — replaced by detect_period.py + replay_fields.py

This script interpolates field data to phase-aligned points, introducing artifacts.
The new pipeline saves RAW (non-interpolated) fields at exact step indices.

Keep this file for reference only. Do NOT rely on its output for CCD analysis.

Usage (old, DEPRECATED):
    python scripts/resample.py       # <-- DO NOT USE
"""
from __future__ import annotations

import json
import os
import sys

import numpy as np

_SRC = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))
if _SRC not in sys.path:
    sys.path.insert(0, _SRC)

from CCD_analysis.configs import SCENES, DATA_DIR
from CCD_analysis.utils.resampling import (
    detect_dominant_frequency, detect_cycle_stability, phase_resample,
)

N_CYCLES = 4
N_PTS = 24

CV_T_STRICT = 0.10
CV_T_RELAXED = 0.12
DELTA_F_STRICT = 0.10
DELTA_F_RELAXED = 0.20

pr = lambda *a, **kw: print(*a, **kw, flush=True)


def run():
    periodic = [name for name, cfg in SCENES.items()
                if cfg["target_type"] == "periodic"]
    pr(f"Periodic cases: {periodic}")

    for name in periodic:
        pr(f"\n=== {name} ===")
        cfg = SCENES[name]
        data_dir = os.path.join(DATA_DIR, cfg["scene_id"], name)
        meta_path = os.path.join(data_dir, "meta.json")
        sens_path = os.path.join(data_dir, "sensors.npz")
        fields_path = os.path.join(data_dir, "fields.npz")
        controlled_path = os.path.join(data_dir, "controlled.npz")

        print(f"\n=== {name} ===")

        # Load sensor data
        if os.path.isfile(controlled_path):
            d = np.load(controlled_path)
        elif os.path.isfile(sens_path):
            d = np.load(sens_path)
        else:
            print(f"  SKIP: no sensor data")
            continue

        sensors = d.get("sensors")
        if sensors is None or len(sensors) < 30:
            print(f"  SKIP: insufficient sensor data ({len(sensors) if sensors is not None else 0})")
            continue

        si = cfg["sample_interval"]
        signal = sensors[:, 3]  # centre sensor v

        # Frequency and stability
        f_case, T_case, _ = detect_dominant_frequency(signal, float(si))
        cv_T, mean_T, cy_lengths = detect_cycle_stability(signal, float(si))
        print(f"  f={f_case:.6f}, T={T_case:.0f}, CV_T={cv_T:.4f}")

        # Gate check
        N_raw = mean_T / si if mean_T > 0 else 0
        rho = 24.0 / N_raw if N_raw > 0 else 99
        delta_f = abs(f_case - f_case) / (f_case + 1e-12)
        if cv_T <= CV_T_STRICT and delta_f <= DELTA_F_STRICT:
            gate = "strict"
        elif cv_T <= CV_T_RELAXED and delta_f <= DELTA_F_RELAXED:
            gate = "relaxed"
        else:
            gate = "auxiliary"
        print(f"  gate={gate}, N_raw/cycle={N_raw:.1f}, rho_interp={rho:.2f}")

        if gate not in ("strict", "relaxed"):
            print(f"  SKIP: does not pass period gate")
            continue

        # Find cycles
        y = signal - np.mean(signal)
        crossings = np.where((np.sign(y[:-1]) < 0) & (np.sign(y[1:]) > 0))[0]
        if len(crossings) < N_CYCLES + 1:
            print(f"  SKIP: only {len(crossings)} cycles")
            continue

        # Select best N_CYCLES
        cycle_lens = np.diff(crossings)
        T_exp = T_case / si if T_case > 0 else N_raw
        best_score, best_start = float("inf"), 0
        for i in range(len(cycle_lens) - N_CYCLES + 1):
            score = np.sum((cycle_lens[i:i+N_CYCLES] - T_exp) ** 2)
            if score < best_score:
                best_score, best_start = score, i
        selected = list(crossings[best_start:best_start + N_CYCLES + 1])

        # Resample
        rs_sensors = phase_resample(sensors, selected, n_pts=N_PTS)

        out = {"sensors": rs_sensors, "n_cycles": N_CYCLES, "n_pts": N_PTS,
               "gate": gate, "selected_crossings": selected}

        # Forces
        forces = d.get("forces")
        if forces is not None and forces.ndim == 2:
            out["forces"] = phase_resample(forces, selected, n_pts=N_PTS)

        # Actions
        actions = d.get("actions")
        if actions is not None and actions.ndim == 2:
            out["actions"] = phase_resample(actions, selected, n_pts=N_PTS)

        fd = None
        # Fields (from controlled.npz or fields.npz)
        if os.path.isfile(controlled_path) and "ux" not in d:
            ol_path = os.path.join(data_dir, "open_loop_fields.npz")
            if os.path.isfile(ol_path):
                fd = np.load(ol_path)
        elif os.path.isfile(fields_path):
            fd = np.load(fields_path)

        if fd is not None and "ux" in fd:
            ux, uy = fd["ux"], fd["uy"]
            if len(ux) >= selected[-1]:
                nx, ny = ux.shape[2], ux.shape[1]
                field_flat = np.column_stack([ux.reshape(len(ux), -1),
                                              uy.reshape(len(uy), -1)])
                rs_fields = phase_resample(field_flat, selected, n_pts=N_PTS)
                half = rs_fields.shape[-1] // 2
                out["ux"] = rs_fields[:, :, :half].reshape(N_CYCLES, N_PTS, ny, nx)
                out["uy"] = rs_fields[:, :, half:].reshape(N_CYCLES, N_PTS, ny, nx)

        # Save
        resample_dir = os.path.join(DATA_DIR, "resampled", name)
        os.makedirs(resample_dir, exist_ok=True)

        save_dict = {"sensors": out["sensors"], "n_cycles": N_CYCLES, "n_pts": N_PTS}
        for k in ["forces", "actions", "ux", "uy"]:
            if k in out:
                save_dict[k] = out[k]
        np.savez_compressed(os.path.join(resample_dir, "resampled.npz"), **save_dict)

        meta = {"case": name, "gate": gate, "f_case": f_case, "CV_T": cv_T,
                "N_raw_per_cycle": N_raw, "rho_interp": rho,
                "n_cycles": N_CYCLES, "n_pts": N_PTS,
                "has_fields": "ux" in out}
        with open(os.path.join(resample_dir, "meta.json"), "w") as f:
            json.dump(meta, f, indent=2)
        pr(f"  Saved: {resample_dir} ({'fields' if meta['has_fields'] else 'no fields'})")

        d.close()
        if fd is not None:
            fd.close()

    print("\nDone.")


if __name__ == "__main__":
    run()
