def fw_events(file, filter_ip, filter_type, clients_dir, limit):
    """Format firewall drop events with dedup and counts"""
    import glob
    proto_map = {1: 'icmp', 6: 'tcp', 17: 'udp'}

    ip_to_name = {}
    for conf in glob.glob(f"{clients_dir}/*.conf"):
        name = os.path.basename(conf).replace('.conf', '')
        try:
            with open(conf) as f:
                for line in f:
                    if line.startswith('Address'):
                        ip = line.split('=')[1].strip().split('/')[0]
                        ip_to_name[ip] = name
        except:
            pass

    events = []
    last_seen = {}

    try:
        with open(file) as f:
            for line in f:
                try:
                    e = json.loads(line.strip())
                    src = e.get('src_ip', '')
                    if not src:
                        continue
                    if filter_ip and src != filter_ip:
                        continue
                    dst    = e.get('dest_ip', '')
                    port   = e.get('dest_port', '')
                    proto  = e.get('ip.protocol', 0)
                    key    = (src, dst, port, proto)
                    ts_str = e.get('timestamp', '')
                    try:
                        from datetime import datetime
                        ts = datetime.fromisoformat(ts_str).timestamp()
                    except:
                        ts = 0
                    windows = {1: 5, 6: 30, 17: 10}
                    window  = windows.get(proto, 10)
                    if key in last_seen and (ts - last_seen[key]) < window:
                        continue
                    last_seen[key] = ts
                    events.append(e)
                except:
                    pass
    except:
        pass

    # Dedup consecutive same src+dst+port within 60s with count
    deduped = []
    counts  = []
    for e in events:
        ts_str = e.get('timestamp', '')
        try:
            from datetime import datetime
            ts = datetime.fromisoformat(ts_str).timestamp()
        except:
            ts = 0
        src   = e.get('src_ip', '')
        dst   = e.get('dest_ip', '')
        port  = e.get('dest_port', '')
        proto = e.get('ip.protocol', 0)
        key   = (src, dst, port, proto)

        if deduped and counts:
            prev = deduped[-1]
            try:
                prev_ts = datetime.fromisoformat(prev.get('timestamp','')).timestamp()
            except:
                prev_ts = 0
            prev_key = (prev.get('src_ip',''), prev.get('dest_ip',''),
                        prev.get('dest_port',''), prev.get('ip.protocol',0))
            if key == prev_key and (ts - prev_ts) < 60:
                counts[-1] += 1
                continue

        deduped.append(e)
        counts.append(1)

    grouped = []
    group_counts = []
    for e in deduped:
        ts_str = e.get('timestamp', '')
        try:
            from datetime import datetime
            dt = datetime.fromisoformat(ts_str)
            # Truncate to minute for grouping
            minute_key = dt.strftime('%Y-%m-%d %H:%M')
        except:
            minute_key = ts_str[:16]
        
        src   = e.get('src_ip', '')
        dst   = e.get('dest_ip', '')
        port  = e.get('dest_port', '')
        proto = e.get('ip.protocol', 0)
        key   = (minute_key, src, dst, proto)  # group within same minute
        
        if grouped and group_counts:
            prev = grouped[-1]
            try:
                prev_dt = datetime.fromisoformat(prev.get('timestamp',''))
                prev_minute = prev_dt.strftime('%Y-%m-%d %H:%M')
            except:
                prev_minute = ''
            prev_key = (prev_minute, prev.get('src_ip',''), 
                        prev.get('dest_ip',''), prev.get('ip.protocol',0))
            if key == prev_key:
                group_counts[-1] += 1
                continue
        
        grouped.append(e)
        group_counts.append(1)

    for e, count in zip(deduped[-int(limit):], counts[-int(limit):]):
        ts = e.get('timestamp', '')
        try:
            from datetime import datetime
            dt = datetime.fromisoformat(ts)
            ts = dt.strftime(DATETIME_FMT)
        except:
            pass
        src       = e.get('src_ip', '—')
        dst       = e.get('dest_ip', '—')
        port      = e.get('dest_port', '')
        proto_num = e.get('ip.protocol', 0)
        proto     = proto_map.get(proto_num, str(proto_num))
        dst_str   = f"{dst}:{port}" if port else dst
        client    = ip_to_name.get(src, src)
        if filter_type and not client.startswith(filter_type + '-'):
            continue
        count_str = f" (x{count})" if count > 1 else ""
        print(f"{ts}|{client}|{dst_str}|{proto}{count_str}")