"""Adaptive threshold computation based on per-signer signal statistics."""

import numpy as np

from ..constants import LIP_EXPR_INDICES


def compute_adaptive_thresholds(pose, jaw_pose, expression, valid, *, eyelid=None, verbose=False):
    """Compute per-signer adaptive thresholds from signal statistics."""
    thresholds = {}

    n = len(pose) if pose is not None else (len(eyelid) if eyelid is not None else 0)
    mask = valid if valid is not None else np.ones(n, dtype=bool)

    if eyelid is not None:
        el = eyelid[mask]
        el_nz = el[el > 0]
        if len(el_nz) > 100:
            el_std = float(np.std(el_nz))
            prominence = max(0.025, min(0.5 * el_std, 0.10))
            thresholds["prominence"] = prominence
            if verbose:
                el_mean = float(np.mean(el_nz))
                print(
                    f"  Eyelid: mean={el_mean:.4f}, "
                    f"std={el_std:.4f} -> prominence={prominence:.4f}"
                )

    if pose is not None:
        pitch = pose[mask, 0].astype(np.float64)
        yaw = pose[mask, 1].astype(np.float64)
        roll = pose[mask, 2].astype(np.float64)

        pitch_vel = np.abs(np.diff(pitch))
        yaw_vel = np.abs(np.diff(yaw))

        pitch_std = float(np.std(pitch))
        pitch_vel_p75 = float(np.percentile(pitch_vel, 75)) if len(pitch_vel) > 10 else 0.01
        nod_amp = max(0.025, min(0.5 * pitch_std, 2.5 * pitch_vel_p75))
        thresholds["nod_amplitude"] = nod_amp

        yaw_std = float(np.std(yaw))
        yaw_vel_p75 = float(np.percentile(yaw_vel, 75)) if len(yaw_vel) > 10 else 0.02
        shake_amp = max(0.035, min(0.5 * yaw_std, 2.5 * yaw_vel_p75))
        thresholds["shake_amplitude"] = shake_amp

        roll_std = float(np.std(roll))
        tilt_thresh = max(0.03, 0.8 * roll_std)
        thresholds["tilt_threshold"] = tilt_thresh

        if verbose:
            print(
                f"  Signer stats -- pitch: std={pitch_std:.4f}, "
                f"yaw: std={yaw_std:.4f}, roll: std={roll_std:.4f}"
            )

    if jaw_pose is not None:
        jaw = jaw_pose[mask, 0].astype(np.float64)
        jaw_mean = float(np.mean(jaw))
        jaw_std = float(np.std(jaw))
        mouth_thresh = max(0.03, jaw_mean + 0.5 * jaw_std)
        thresholds["mouth_threshold"] = mouth_thresh

    if expression is not None and expression.shape[1] >= 38:
        raise_raw = expression[mask][:, [8, 37]]
        raise_std = float(np.mean(np.std(raise_raw, axis=0)))
        if raise_std < 0.01:
            thresholds["eyebrow_threshold"] = 0.8
        else:
            thresholds["eyebrow_threshold"] = 1.2

    if eyelid is not None:
        el = eyelid[mask]
        el_nz = el[el > 0]
        if len(el_nz) > 100:
            el_std = float(np.std(el_nz))
            squint_thresh = max(0.02, min(0.5 * el_std, 0.08))
            thresholds["squint_threshold"] = squint_thresh

    if expression is not None and expression.shape[1] >= max(LIP_EXPR_INDICES) + 1:
        lip_raw = expression[mask][:, LIP_EXPR_INDICES]
        lip_vel = np.diff(lip_raw, axis=0)
        lip_vel_mag = np.sqrt(np.sum(lip_vel**2, axis=1))
        lip_vel_mean = float(np.mean(lip_vel_mag))
        lip_vel_std = float(np.std(lip_vel_mag))
        lip_thresh = max(0.05, min(lip_vel_mean + lip_vel_std, 0.40))
        thresholds["lip_threshold"] = lip_thresh

    if verbose:
        print(
            "  Adaptive thresholds: "
            + ", ".join(f"{k}={v:.4f}" for k, v in sorted(thresholds.items()))
        )

    return thresholds
