from __future__ import annotations

from dataclasses import dataclass, field


@dataclass(frozen=True)
class StreamProfile:
    stream_id: str
    name: str
    entity_field: str
    timestamp_field: str
    categorical_fields: tuple[str, ...] = ()
    numeric_fields: tuple[str, ...] = ()
    detectors: dict[str, dict[str, object]] = field(default_factory=dict)
    field_weights: dict[str, object] = field(default_factory=dict)


def _detectors(value: object) -> dict[str, dict[str, object]]:
    if not isinstance(value, dict):
        return {}
    output: dict[str, dict[str, object]] = {}
    for name, settings in value.items():
        if str(name) not in {"auth_failure", "dns_query", "deny_action"} or not isinstance(settings, dict):
            continue
        try:
            minimum = max(1, int(settings.get("minimum", 1)))
            z_threshold = max(1.0, float(settings.get("z_threshold", 3.0)))
        except (TypeError, ValueError):
            continue
        output[str(name)] = {"enabled": bool(settings.get("enabled", True)), "minimum": minimum, "z_threshold": z_threshold}
    return output


def _field_weights(value: object) -> dict[str, object]:
    if not isinstance(value, dict):
        return {}
    output: dict[str, object] = {}
    for key, setting in value.items():
        if isinstance(setting, dict):
            nested: dict[str, float] = {}
            for nested_key, nested_value in setting.items():
                try:
                    nested[str(nested_key).lower()] = max(0.0, min(5.0, float(nested_value)))
                except (TypeError, ValueError):
                    continue
            if nested:
                output[str(key).lower()] = nested
            continue
        try:
            output[str(key).lower()] = max(0.0, min(5.0, float(setting)))
        except (TypeError, ValueError):
            continue
    return output


def parse_profiles(value: object) -> dict[str, StreamProfile]:
    profiles: dict[str, StreamProfile] = {}
    for item in value if isinstance(value, list) else []:
        if not isinstance(item, dict):
            continue
        stream_id = str(item.get("stream_id", "")).strip()
        entity = str(item.get("entity_field", "")).strip()
        timestamp = str(item.get("timestamp_field", "timestamp")).strip()
        if not stream_id or not entity:
            continue
        detectors = _detectors(item.get("detectors", {}))
        field_weights = _field_weights(item.get("field_weights", {}))
        profiles[stream_id] = StreamProfile(
            stream_id, str(item.get("name", "")).strip() or stream_id, entity, timestamp,
            tuple(str(field) for field in item.get("categorical_fields", []) if field),
            tuple(str(field) for field in item.get("numeric_fields", []) if field),
            detectors,
            field_weights,
        )
    return profiles
