from scapy.all import IP, IPv6, TCP, UDP, DNS


def extract_timeline(packets):
    events = []
    if not packets:
        return events

    base_time = float(packets[0].time)

    for pkt in packets:
        if not hasattr(pkt, "time"):
            continue

        t = round(float(pkt.time) - base_time, 3)

        if pkt.haslayer(IP):
            src, dst = pkt[IP].src, pkt[IP].dst
        elif pkt.haslayer(IPv6):
            src, dst = pkt[IPv6].src, pkt[IPv6].dst
        else:
            continue

        if pkt.haslayer(DNS) and pkt.haslayer(UDP):
            dns = pkt[DNS]
            if dns.qr == 0 and dns.qd:
                events.append({
                    "time": t,
                    "type": "DNS_QUERY",
                    "src": src,
                    "dst": dst,
                    "detail": dns.qd.qname.decode(errors="ignore"),
                })
            elif dns.qr == 1 and dns.an:
                events.append({
                    "time": t,
                    "type": "DNS_RESPONSE",
                    "src": src,
                    "dst": dst,
                    "detail": f"{dns.an.rrname.decode(errors='ignore')} → {dns.an.rdata}",
                })

        if pkt.haslayer(TCP) and pkt[TCP].flags & 0x02:
            events.append({
                "time": t,
                "type": "TCP_CONNECT",
                "src": f"{src}:{pkt[TCP].sport}",
                "dst": f"{dst}:{pkt[TCP].dport}",
                "detail": "SYN",
            })

    return sorted(events, key=lambda x: x["time"])
