from __future__ import annotations

from collections import defaultdict, Counter
from dataclasses import dataclass
from typing import Dict, List, Tuple, Iterable
from datetime import timedelta

from ..p2p.events import P2PEvent


@dataclass(frozen=True)
class VariantResult:
    variant: Tuple[str, ...]
    count: int


def variants(events: Iterable[P2PEvent], max_variants: int = 10) -> List[VariantResult]:
    per_case: Dict[str, List[P2PEvent]] = defaultdict(list)
    for e in events:
        per_case[e.case_id].append(e)

    seqs = []
    for case_id, evs in per_case.items():
        evs_sorted = sorted(evs, key=lambda x: x.ts)
        seqs.append(tuple(e.event_type for e in evs_sorted))

    c = Counter(seqs)
    most = c.most_common(max_variants)
    return [VariantResult(variant=k, count=v) for k, v in most]


def lead_time(events: Iterable[P2PEvent], start: str, end: str) -> Dict[str, timedelta]:
    """
    Returns per-case lead time between first 'start' and first 'end' event.
    """
    per_case: Dict[str, List[P2PEvent]] = defaultdict(list)
    for e in events:
        per_case[e.case_id].append(e)

    out: Dict[str, timedelta] = {}
    for case_id, evs in per_case.items():
        evs_sorted = sorted(evs, key=lambda x: x.ts)
        s = next((e.ts for e in evs_sorted if e.event_type == start), None)
        t = next((e.ts for e in evs_sorted if e.event_type == end), None)
        if s and t and t >= s:
            out[case_id] = t - s
    return out


def bottlenecks(lead_times: Dict[str, timedelta], top_n: int = 10) -> List[Tuple[str, timedelta]]:
    """
    Returns slowest cases by lead time.
    """
    return sorted(lead_times.items(), key=lambda x: x[1], reverse=True)[:top_n]

