# Copyright (c) 2026 PULSE Contributors. Proprietary. All rights reserved.
# See LICENSE file for details.
"""
Wants Classify: Domain classification, priority computation, dedup logic.

Extracted from wants_parser.py for Law 7 compliance.
"""

import re
from typing import Dict, List


# Domain keywords for auto-classification
DOMAIN_KEYWORDS = {
    "language": [
        "translat", "language", "unicode", "script", "guard", "chunk",
        "tokenize", "parse", "encode", "decode", "linguistic", "nlp"
    ],
    "tts": [
        "voice", "tts", "speech", "audio", "clone", "speak",
        "synthesize", "prosody", "intonation"
    ],
    "detection": [
        "detect", "glotlid", "dialect", "identify",   
        "recognize", "classify", "predict", "infer"   
    ],
    "ui": [
        "button", "keyboard", "menu", "display", "manifesto", "label",
        "widget", "component", "layout", "screen", "view",
        "dashboard", "chart", "recharts", "tailwind", "glassmorphism",
        "css", "styling", "frontend", "react", "vite", "vercel"
    ],
    "handler": [
        "handler", "command", "callback", "route", "message",
        "dispatch", "trigger", "event", "webhook"     
    ],
    "neural_infra": [
        "brain", "daemon", "evidence", "pattern",
        "orchestrat", "synthesiz", "hippocampus", "consolidat",
        "extraction", "knowledge_graph", "fts", "reconsolidat",
        "boot", "neural_state", "session_lifecycle"   
    ],
    "architecture": [
        "refactor", "split", "module", "layer", "core",
        "structure", "import", "abstract", "interface",
        "coupling", "decoupl"
    ],
    "testing": [
        "test", "verify", "check", "assert", "coverage",
        "validate", "debug", "benchmark", "profile",  
        "smoke_test", "integration_test", "unit_test" 
    ],
    "security": [
        "auth", "token", "credential", "encrypt", "privacy", "sanitize",
        "leak", "scrub", "signature", "permission",   
        "pii", "redact", "hash", "seal", "sign"       
    ],
    "deployment": [
        "deploy", "build", "release", "docker", "ci/cd",
        "pypi", "npm", "install", "version"
    ],
    "governance": [
        "law", "constitution", "rule", "compliance", "policy",
        "titan", "regulation", "enforcement",
        "asop", "sacred", "immutable"
    ],
    "data_quality": [
        "dedup", "quality_gate", "salience", "confidence", "threshold", "filter"
    ],
    "performance": [
        "latency", "throughput", "bottleneck", "speedup", "cache",
        "optimization", "perf", "timeout", "slow", "profil",
        "memory_usage", "cpu", "startup_time"
    ],
    "swarm": [
        "worker", "swarm", "headless", "autopilot", "spawn",
        "concurrent", "parallel", "batch", "task_board", "dispatch",
        "complete_task", "task_ops", "relay", "decompos"
    ],
    "api": [
        "endpoint", "rest", "fastapi", "cors", "http",
        "request", "response", "api_key", "bearer", "openapi", "server"
    ],
    "data_ops": [
        "sqlite", "database", "migration", "sql", "jsonl",
        "schema", "persist", "table", "column", "backup",
        "json", "atomic_write", "filelock", "wal", "checkpoint"
    ],
    "model_ops": [
        "llm", "anthropic", "gemini", "openai", "ollama",
        "qwen", "provider", "model_id", "embedding", "token_limit",
        "claude", "sonnet", "opus", "haiku", "grok", "codex",
        "tier", "premium"
    ],
    "roadmap": [
        "roadmap", "milestone", "sprint", "future", "upcoming",
        "phase", "priority", "backlog"
    ],
}

# Priority signals
HIGH_PRIORITY_SIGNALS = [
    "urgent", "critical", "asap", "immediately", "now",
    "important", "must", "required", "blocking",
]
LOW_PRIORITY_SIGNALS = [
    "maybe", "someday", "when possible", "nice to have",
    "eventually", "low priority", "optional",
]

# Privacy/Sensitivity signals
SENSITIVE_PATTERNS = [
    r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}",  # Emails
    r"sk-[0-9A-Za-z]{48}",                             # OpenAI Keys
    r"AIza[0-9A-Za-z-_]{35}",                          # Google Keys
    r"(?:password|secret|key|token|credential)\s*[:=]\s*\S+", # Generic secrets
]
PERSONAL_KEYWORDS = [
    "personal", "private", "my plan", "personal plan", "personal reasoning",
    "internal draft", "private draft",
]


def _detect_visibility(text: str) -> str:
    """Detect if text contains sensitive or personal info."""
    text_lower = text.lower()
    for pattern in SENSITIVE_PATTERNS:
        if re.search(pattern, text):
            return "personal"
    for kw in PERSONAL_KEYWORDS:
        if kw in text_lower:
            return "personal"
    return "public"


def _compute_priority(text: str, domain: str = "") -> int:
    """Compute priority score (1-10) from text signals and domain context."""
    score = 5  # default medium

    for signal in HIGH_PRIORITY_SIGNALS:
        if signal in text:
            score = min(10, score + 2)
            break

    for signal in LOW_PRIORITY_SIGNALS:
        if signal in text:
            score = max(1, score - 2)
            break

    # Exclamation marks boost priority
    excl_count = text.count("!")
    if excl_count >= 2:
        score = min(10, score + 1)

    # ALL CAPS words boost priority
    words = text.split()
    caps_count = sum(1 for w in words if w.isupper() and len(w) > 2)
    if caps_count >= 2:
        score = min(10, score + 1)

    # Structural domains affect everything downstream — boost priority
    if domain in ("governance", "architecture"):
        score = min(10, score + 1)

    return score


def _classify_domain(text: str) -> str:
    """Classify text into brain domain by keyword matching.

    Requires score >= 2 for confident classification to prevent ambiguous
    single-keyword matches (e.g., 'bridge' matching neural_infra for physical bridges).
    """
    scores = {}
    text_lower = text.lower()

    for domain, keywords in DOMAIN_KEYWORDS.items():
        score = sum(1 for kw in keywords if kw in text_lower)
        if score > 0:
            scores[domain] = score

    if not scores:
        return "general"

    best_domain = max(scores, key=scores.get)
    best_score = scores[best_domain]

    # Require 1+ keyword match for classification
    # A single keyword match is sufficient for domain routing
    if best_score < 2:
        return "general"

    return best_domain


def _deduplicate(items: List[Dict]) -> List[Dict]:
    """Remove near-duplicate items by first key content."""
    seen = set()
    unique = []
    for item in items:
        # Use first meaningful value as dedup key
        key = None
        for k in ("want", "dont_want"):
            if k in item:
                key = item[k].strip().lower()[:50]
                break
        if key and key not in seen:
            seen.add(key)
            unique.append(item)
    return unique
