import numpy as np

def detect_step_segments(signal, 
                         diff_threshold=0.05, 
                         min_length=20):
    """
    Erkennt automatisch Step-Up/Step-Down-Segmente aus einem gemessenen Tiefpass-Signal.
    Arbeitet über die erste Ableitung statt über absolute Schwellen.
    
    signal : 1D array
    diff_threshold : float  
        Minimale Änderung pro Sample, um einen Step zu erkennen.
        Für deine Daten funktioniert ~0.05 gut.
    min_length : int  
        Minimale Länge eines Segments (Samples).
        
    Returns:
        list of (start_idx, end_idx)
    """
    
    s = np.asarray(signal)
    diff = np.diff(s)

    # Step-Up dort, wo diff stark positiv ist
    ups = np.where(diff > diff_threshold)[0]

    # Step-Down dort, wo diff stark negativ ist
    downs = np.where(diff < -diff_threshold)[0]

    segments = []

    # Beide Listen sind ungeordnet, aber Step-Up sollte vor Step-Down kommen
    up_idx = 0
    down_idx = 0

    while up_idx < len(ups) and down_idx < len(downs):
        start = ups[up_idx]

        # Nimm das nächste Down-Event, das nach dem Start liegt
        while down_idx < len(downs) and downs[down_idx] <= start:
            down_idx += 1

        if down_idx >= len(downs):
            break

        end = downs[down_idx]

        if end - start >= min_length:
            segments.append((start, end))

        up_idx += 1
        down_idx += 1

    return merge_close_segments(segments)

def merge_close_segments(segments, max_start_gap=10, max_end_gap=10):
    """
    Fasst Segmente zusammen, deren Starts und Ends nahe beieinander liegen.
    
    segments : list of (start, end)
    max_start_gap : max Abstand zwischen Starts, um zusammenzufassen
    max_end_gap   : max Abstand zwischen Ends, um zusammenzufassen

    Returns:
        merged list of (start, end)
    """
    if not segments:
        return []

    # Sortiere nach Start
    segments = sorted(segments, key=lambda x: x[0])

    merged = []
    current_start, current_end = segments[0]

    for start, end in segments[1:]:
        # Prüfen, ob sowohl Start als auch End nah genug sind
        if start - current_start <= max_start_gap and abs(end - current_end) <= max_end_gap:
            # Segment gehört zum Cluster
            current_end = max(current_end, end)
        else:
            merged.append((current_start, current_end))
            current_start, current_end = start, end

    merged.append((current_start, current_end))
    return merged


def laenge_laengstes_array(arrays):
    """
    Gibt die Länge des längsten Arrays in einem Array von Arrays zurück.

    Parameters:
    arrays (list of list or ndarray): Liste von Arrays

    Returns:
    int: Länge des längsten Arrays
    """
    # Konvertiere in ein NumPy-Array, um die Länge der inneren Arrays zu messen
    laengen = np.array([len(a) for a in arrays])
    return np.max(laengen)
