"""Phase 6E: Auto-Pattern Generation — regex from semantic extraction misses."""
import json
import re
import uuid
from datetime import datetime, timezone
from pulse.core.paths import get_state_dir, get_brain_dir
from pulse.core import event_bus

MISSES_LOG = get_state_dir() / "semantic_misses.jsonl"
GENERATED_PATTERNS = get_brain_dir() / "Patterns" / "generated_patterns.json"


def log_semantic_miss(text: str, domain: str = "general"):
    """Called by semantic_extractor when regex fails but embedding succeeds."""
    MISSES_LOG.parent.mkdir(parents=True, exist_ok=True)
    entry = {"text": text[:200], "domain": domain, "timestamp": datetime.now(timezone.utc).isoformat()}
    with open(MISSES_LOG, "a", encoding="utf-8") as f:
        f.write(json.dumps(entry) + "\n")


def evolve_patterns(verbose=False) -> dict:
    """
    Process accumulated semantic misses. If 3+ similar misses found,
    generate candidate regex pattern.
    """
    if not MISSES_LOG.exists():
        return {"status": "no_misses"}

    # Load misses
    misses = []
    with open(MISSES_LOG, "r", encoding="utf-8") as f:
        for line in f:
            line = line.strip()
            if line:
                try:
                    misses.append(json.loads(line))
                except Exception:
                    pass

    if len(misses) < 3:
        return {"status": "insufficient_misses", "count": len(misses)}

    # Cluster by leading word patterns (simple token-based clustering)
    clusters = {}
    for miss in misses:
        text = miss.get("text", "")
        tokens = text.split()[:3]
        key = " ".join(tokens).lower() if tokens else "unknown"
        clusters.setdefault(key, []).append(text)

    # Generate patterns from clusters with 3+ members
    generated = _load_generated()
    new_patterns = 0

    for key, texts in clusters.items():
        if len(texts) < 3:
            continue

        # Check not already generated
        if any(p.get("cluster_key") == key for p in generated.get("patterns", [])):
            continue

        candidate = _generate_regex(texts)
        if candidate:
            pattern_entry = {
                "id": f"gen_{uuid.uuid4().hex[:8]}",
                "cluster_key": key,
                "regex": candidate,
                "date_generated": datetime.now(timezone.utc).isoformat(),
                "source_count": len(texts),
                "active": True,
                "validation_hits": 0,
            }
            generated.setdefault("patterns", []).append(pattern_entry)
            new_patterns += 1
            if verbose:
                print(f"  [EVOLVE] New pattern from '{key}': {candidate}")

    if new_patterns > 0:
        _save_generated(generated)
        event_bus.publish("pattern.evolved", "pattern_evolution", {"new_patterns": new_patterns})

    return {"new_patterns": new_patterns, "clusters_found": len(clusters)}


def _generate_regex(texts: list) -> str:
    """Generate a candidate regex from similar texts."""
    if not texts:
        return ""
    # Find common prefix/suffix tokens
    token_sets = [t.split() for t in texts]
    if not token_sets:
        return ""

    # Find tokens that appear in ALL samples
    common = set(token_sets[0])
    for ts in token_sets[1:]:
        common &= set(ts)

    if not common:
        return ""

    # Build regex: common tokens as literals, variable parts as \\S+
    first = texts[0].split()
    parts = []
    for token in first:
        if token.lower() in {t.lower() for t in common}:
            parts.append(re.escape(token))
        else:
            parts.append(r"\S+")

    candidate = r"\b" + r"\s+".join(parts) + r"\b"

    # Validate: must match at least 60% of source texts
    hits = sum(1 for t in texts if re.search(candidate, t, re.IGNORECASE))
    if hits / len(texts) < 0.6:
        return ""

    return candidate


def _load_generated() -> dict:
    if not GENERATED_PATTERNS.exists():
        return {"patterns": []}
    try:
        return json.loads(GENERATED_PATTERNS.read_text(encoding="utf-8"))
    except Exception:
        return {"patterns": []}


def _save_generated(data: dict):
    GENERATED_PATTERNS.parent.mkdir(parents=True, exist_ok=True)
    GENERATED_PATTERNS.write_text(json.dumps(data, indent=2), encoding="utf-8")
