from __future__ import annotations

import json
from pathlib import Path
from typing import Any

from one_run.constants import DEFAULT_RUNS_DIR
from one_run.utils.timefmt import iso_short


def normalize_values(values: list[str] | None) -> set[str]:
    if not values:
        return set()
    return {str(v).strip() for v in values if str(v).strip()}


def format_event_line(payload: dict[str, Any]) -> str:
    timestamp = iso_short(payload.get("timestamp"))
    run_id = payload.get("run_id", "?")
    event = payload.get("event", "?")
    state = payload.get("state", "-")
    message = payload.get("message", "-")
    return f"[{run_id}] timestamp={timestamp} event={event} state={state} message={message}"


def load_run_tags(project_root: Path, run_id: str, cache: dict[str, set[str]]) -> set[str]:
    cached = cache.get(run_id)
    if cached is not None:
        return cached
    metadata_path = project_root / DEFAULT_RUNS_DIR / run_id / "metadata.json"
    if not metadata_path.exists():
        cache[run_id] = set()
        return set()
    try:
        payload = json.loads(metadata_path.read_text(encoding="utf-8"))
    except json.JSONDecodeError:
        cache[run_id] = set()
        return set()
    raw_tags = payload.get("tags")
    if not isinstance(raw_tags, list):
        cache[run_id] = set()
        return set()
    tags = {str(tag).strip() for tag in raw_tags if str(tag).strip()}
    cache[run_id] = tags
    return tags


def event_matches(
    payload: dict[str, Any],
    *,
    allowed_events: set[str],
    allowed_states: set[str],
    required_tags: set[str],
    project_root: Path,
    tag_cache: dict[str, set[str]],
) -> bool:
    event_name = str(payload.get("event", "")).strip()
    state = str(payload.get("state", "")).strip()
    if allowed_events and event_name not in allowed_events:
        return False
    if allowed_states and state not in allowed_states:
        return False
    if not required_tags:
        return True
    run_id = str(payload.get("run_id", "")).strip()
    if not run_id:
        return False
    tags = load_run_tags(project_root, run_id, tag_cache)
    return required_tags.issubset(tags)
