"""
mdmin — Tokenizer-Aware Synonym Replacement

BPE tokenizers (cl100k_base, o200k_base) break words into subword tokens.
"approximately" = 3 tokens, "~" = 1 token — same meaning to an LLM.

Categories:
  1. Technical abbreviations (authentication → auth)
  2. Symbol replacements (approximately → ~)
  3. Shorter synonyms (utilize → use)
  4. Contractions (cannot → can't)
  5. Structural cleanup
  6. Context-sensitive abbreviations (web server → web srv)
"""
from __future__ import annotations
import re

_I = re.IGNORECASE

# Format: (compiled_pattern, replacement, estimated_token_savings)
# replacement is str (with \\1 backrefs) or callable(match) -> str
# savings == 0 entries are skipped at application time

TOKEN_SYNONYMS: dict[str, list] = {

    # ─── TIER 1: Technical Abbreviations ───────────────────────────────────
    "technical": [
        (re.compile(r"\bauthentication\b", _I), "auth", 2),
        (re.compile(r"\bauthorization\b", _I), "authz", 2),
        (re.compile(r"\bconfiguration\b", _I), "config", 2),
        (re.compile(r"\bconfigurations\b", _I), "configs", 2),
        (re.compile(r"\bimplementation\b", _I), "impl", 3),
        (re.compile(r"\bimplementations\b", _I), "impls", 3),
        (re.compile(r"\benvironment\b", _I), "env", 1),
        (re.compile(r"\benvironments\b", _I), "envs", 1),
        (re.compile(r"\bapplication\b", _I), "app", 2),
        (re.compile(r"\bapplications\b", _I), "apps", 2),
        (re.compile(r"\binformation\b", _I), "info", 2),
        (re.compile(r"\bdocumentation\b", _I), "docs", 2),
        (re.compile(r"\brepository\b", _I), "repo", 2),
        (re.compile(r"\brepositories\b", _I), "repos", 2),
        (re.compile(r"\bdirectory\b", _I), "dir", 1),
        (re.compile(r"\bdirectories\b", _I), "dirs", 1),
        (re.compile(r"\bparameters\b", _I), "params", 2),
        (re.compile(r"\bparameter\b", _I), "param", 2),
        (re.compile(r"\barguments\b", _I), "args", 1),
        (re.compile(r"\bargument\b", _I), "arg", 1),
        (re.compile(r"\btemporary\b", _I), "temp", 1),
        (re.compile(r"\bmaximum\b", _I), "max", 1),
        (re.compile(r"\bminimum\b", _I), "min", 1),
        (re.compile(r"\baverage\b", _I), "avg", 1),
        (re.compile(r"\bspecification\b", _I), "spec", 2),
        (re.compile(r"\bspecifications\b", _I), "specs", 2),
        (re.compile(r"\bdevelopment\b", _I), "dev", 2),
        (re.compile(r"\bproduction\b", _I), "prod", 1),
        (re.compile(r"\boperating system\b", _I), "OS", 2),
        (re.compile(r"\bdatabases\b", _I), "DBs", 1),
        (re.compile(r"\bdatabase\b", _I), "DB", 1),
        (re.compile(r"\bmessage queues?\b", _I), "MQ", 2),
        (re.compile(r"\bcommand[- ]line interface\b", _I), "CLI", 3),
        (re.compile(r"\bgraphical user interface\b", _I), "GUI", 4),
        (re.compile(r"\bapplication programming interface\b", _I), "API", 4),
        (re.compile(r"\buser interface\b", _I), "UI", 2),
        (re.compile(r"\buser experience\b", _I), "UX", 2),
        (re.compile(r"\bcontinuous integration/continuous delivery\b", _I), "CI/CD", 4),
        (re.compile(r"\bcontinuous integration and continuous delivery\b", _I), "CI/CD", 5),
        (re.compile(r"\bcontinuous integration\b", _I), "CI", 2),
        (re.compile(r"\bcontinuous delivery\b", _I), "CD", 2),
        (re.compile(r"\bpull requests\b", _I), "PRs", 2),
        (re.compile(r"\bpull request\b", _I), "PR", 2),
        (re.compile(r"\bversion control\b", _I), "VCS", 2),
        (re.compile(r"\bsource code management\b", _I), "SCM", 3),
        (re.compile(r"\binfrastructure as code\b", _I), "IaC", 3),
        (re.compile(r"\bsoftware as a service\b", _I), "SaaS", 4),
        (re.compile(r"\bplatform as a service\b", _I), "PaaS", 4),
        (re.compile(r"\bsoftware development kit\b", _I), "SDK", 3),
        (re.compile(r"\bidentifiers\b", _I), "IDs", 2),
        (re.compile(r"\bidentifier\b", _I), "ID", 2),
        (re.compile(r"\bJavaScript\b"), "JS", 2),
        (re.compile(r"\bTypeScript\b"), "TS", 2),
        (re.compile(r"\bsynchronous\b", _I), "sync", 1),
        (re.compile(r"\basynchronous(?:ly)?\b", _I), "async", 1),
        (re.compile(r"\bmicroservices\b", _I), "µservices", 1),
        (re.compile(r"\bmicroservice\b", _I), "µservice", 1),
        (re.compile(r"\bregular expressions?\b", _I), "regex", 2),
        (re.compile(r"\bsubscriptions\b", _I), "subs", 1),
        (re.compile(r"\bsubscription\b", _I), "sub", 1),
        (re.compile(r"\btransactions\b", _I), "txns", 1),
        (re.compile(r"\btransaction\b", _I), "txn", 1),
        (re.compile(r"\bexecutable\b", _I), "exec", 1),
        (re.compile(r"\bmanagement\b", _I), "mgmt", 1),
        (re.compile(r"\bperformance\b", _I), "perf", 1),
        (re.compile(r"\breferences\b", _I), "refs", 1),
        (re.compile(r"\breference\b", _I), "ref", 1),
        (re.compile(r"\bgeneration\b", _I), "gen", 1),
        (re.compile(r"\bnavigation\b", _I), "nav", 1),
        (re.compile(r"\blibraries\b", _I), "libs", 1),
        (re.compile(r"\blibrary\b", _I), "lib", 1),
        (re.compile(r"\butilities\b", _I), "utils", 1),
        (re.compile(r"\butility\b", _I), "util", 1),
        (re.compile(r"\bcertificates\b", _I), "certs", 1),
        (re.compile(r"\bcertificate\b", _I), "cert", 1),
        (re.compile(r"\badministrators?\b", _I), "admin", 2),
        (re.compile(r"\badministration\b", _I), "admin", 2),
        (re.compile(r"\bmodifications\b", _I), "mods", 2),
        (re.compile(r"\bmodification\b", _I), "mod", 2),
        (re.compile(r"\bnotifications\b", _I), "notifs", 1),
        (re.compile(r"\bnotification\b", _I), "notif", 1),
        (re.compile(r"\barchitecture\b", _I), "arch", 1),
        (re.compile(r"\binfrastructure\b", _I), "infra", 2),
        (re.compile(r"\bdependencies\b", _I), "deps", 1),
        (re.compile(r"\bdependency\b", _I), "dep", 1),
        (re.compile(r"\bcommunications?\b", _I), "comms", 2),
        (re.compile(r"\borganizations\b", _I), "orgs", 2),
        (re.compile(r"\borganization\b", _I), "org", 2),
        (re.compile(r"\bpermissions\b", _I), "perms", 1),
        (re.compile(r"\bpermission\b", _I), "perm", 1),
        (re.compile(r"\bdeployment\b", _I), "deploy", 1),
        (re.compile(r"\bdeployments\b", _I), "deploys", 1),
        (re.compile(r"\bcredentials\b", _I), "creds", 1),
        (re.compile(r"\bcredential\b", _I), "cred", 1),
        (re.compile(r"\bvalidation\b", _I), "validation", 0),
        (re.compile(r"\btimestamp\b", _I), "ts", 1),
        (re.compile(r"\btimestamps\b", _I), "timestamps", 0),
    ],

    # ─── TIER 2: Symbol Replacements ───────────────────────────────────────
    "symbols": [
        (re.compile(r"\bapproximately (\d)", _I), r"~\1", 2),
        (re.compile(r"\bapproximately\b", _I), "~", 2),
        (re.compile(r"\bgreater than or equal to (\d)", _I), r"≥\1", 4),
        (re.compile(r"\bless than or equal to (\d)", _I), r"≤\1", 4),
        (re.compile(r"\bgreater than (\d)", _I), r">\1", 2),
        (re.compile(r"\bless than (\d)", _I), r"<\1", 2),
        (re.compile(r"\bnot equal to\b", _I), "≠", 3),
        (re.compile(r"\bdoes not equal\b", _I), "≠", 3),
        (re.compile(r"\bplus or minus\b", _I), "±", 2),
        (re.compile(r"\btherefore\b", _I), "∴", 1),
        (re.compile(r"\bfor example,?\s*", _I), "e.g. ", 1),
        (re.compile(r"\bfor instance,?\s*", _I), "e.g. ", 1),
        (re.compile(r"\bthat is to say\b", _I), "i.e.", 3),
        (re.compile(r"\bin other words\b", _I), "i.e.", 2),
        (re.compile(r"\band so on\b", _I), "etc.", 2),
        (re.compile(r"\bet cetera\b", _I), "etc.", 1),
        (re.compile(r"\bpercent\b", _I), "%", 1),
        (re.compile(r"\bpoints to\b", _I), "→", 1),
        (re.compile(r"\bleads to\b", _I), "→", 1),
        (re.compile(r"\bresults in\b", _I), "→", 1),
        (re.compile(r"\bconverts? to\b", _I), "→", 1),
        (re.compile(r"\btransforms? (?:in)?to\b", _I), "→", 1),
        (re.compile(r"\bversus\b", _I), "vs", 1),
        (re.compile(r"\band/or\b", _I), "/", 1),
        (re.compile(r"\bregarding\b", _I), "re:", 1),
        (re.compile(r"\bconcerning\b", _I), "re:", 1),
    ],

    # ─── TIER 3: Shorter Synonyms ───────────────────────────────────────────
    "synonyms": [
        (re.compile(r"\butilize\b", _I), "use", 1),
        (re.compile(r"\butilization\b", _I), "use", 2),
        (re.compile(r"\butilizing\b", _I), "using", 1),
        (re.compile(r"\bdemonstrates?\b", _I), lambda m: "shows" if m.group(0).lower().endswith("s") else "show", 1),
        (re.compile(r"\bdemonstrating\b", _I), "showing", 1),
        (re.compile(r"\bdemonstration\b", _I), "demo", 2),
        (re.compile(r"\bfacilitates?\b", _I), lambda m: "enables" if m.group(0).lower().endswith("s") else "enable", 1),
        (re.compile(r"\bfacilitating\b", _I), "enabling", 1),
        (re.compile(r"\bestablishes?\b", _I), lambda m: "sets up" if m.group(0).lower().endswith("es") else "set up", 1),
        (re.compile(r"\bestablishing\b", _I), "setting up", 1),
        (re.compile(r"\baccomplishes?\b", _I), lambda m: "does" if m.group(0).lower().endswith("es") else "do", 1),
        (re.compile(r"\bcommence\b", _I), "start", 1),
        (re.compile(r"\bterminate\b", _I), "end", 1),
        (re.compile(r"\bterminates\b", _I), "ends", 1),
        (re.compile(r"\bindividuals\b", _I), "people", 1),
        (re.compile(r"\bindividual\b", _I), "person", 1),
        (re.compile(r"\bnevertheless\b", _I), "but", 2),
        (re.compile(r"\bnotwithstanding\b", _I), "despite", 2),
        (re.compile(r"\bfurthermore\b", _I), "also", 1),
        (re.compile(r"\badditionally\b", _I), "also", 1),
        (re.compile(r"\bconsequently\b", _I), "so", 2),
        (re.compile(r"\bsubsequently\b", _I), "then", 2),
        (re.compile(r"\bimmediately\b", _I), "now", 2),
        (re.compile(r"\bsimultaneously\b", _I), "at once", 2),
        (re.compile(r"\bnumerous\b", _I), "many", 1),
        (re.compile(r"\bsufficient\b", _I), "enough", 1),
        (re.compile(r"\binsufficient\b", _I), "not enough", 1),
        (re.compile(r"\brequirements\b", _I), "needs", 1),
        (re.compile(r"\brequirement\b", _I), "need", 1),
        (re.compile(r"\bfunctionality\b", _I), "features", 2),
        (re.compile(r"\bcomponents\b", _I), "parts", 1),
        (re.compile(r"\bcomponent\b", _I), "part", 1),
        (re.compile(r"\bsubsequent\b", _I), "next", 1),
        (re.compile(r"\badditional\b", _I), "more", 1),
        (re.compile(r"\bnecessary\b", _I), "needed", 1),
        (re.compile(r"\bfrequently\b", _I), "often", 1),
        (re.compile(r"\boccasionally\b", _I), "sometimes", 1),
        (re.compile(r"\bsignificant\b", _I), "major", 1),
        (re.compile(r"\bsignificantly\b", _I), "much", 2),
        (re.compile(r"\bconsiderable\b", _I), "big", 1),
        (re.compile(r"\bconsiderably\b", _I), "much", 2),
        (re.compile(r"\bsubstantial\b", _I), "large", 1),
        (re.compile(r"\bsubstantially\b", _I), "much", 2),
        (re.compile(r"\bcommunicates?\b", _I), lambda m: "tells" if m.group(0).lower().endswith("s") else "tell", 1),
        (re.compile(r"\bcommunicating\b", _I), "telling", 1),
        (re.compile(r"\binvestigating?\b", _I), lambda m: "check" if m.group(0).lower().endswith("e") else "checking", 1),
        (re.compile(r"\bdetermines?\b", _I), lambda m: "finds" if m.group(0).lower().endswith("s") else "find", 1),
        (re.compile(r"\bdetermining\b", _I), "finding", 1),
        (re.compile(r"\bmethodology\b", _I), "method", 1),
        (re.compile(r"\bmethodologies\b", _I), "methods", 1),
        (re.compile(r"\btroubleshooting?\b", _I), lambda m: "debugging" if m.group(0).lower().endswith("ing") else "debug", 1),
        (re.compile(r"\bpreviously\b", _I), "before", 1),
        (re.compile(r"\bcurrently\b", _I), "now", 1),
        (re.compile(r"\binitially\b", _I), "first", 1),
        (re.compile(r"\bultimately\b", _I), "finally", 1),
        (re.compile(r"\bspecifically\b", _I), "namely", 1),
        (re.compile(r"\bapproximately\b", _I), "~", 2),
        (re.compile(r"\bautomatically\b", _I), "auto", 2),
        (re.compile(r"\bfundamentally\b", _I), "basically", 1),
    ],

    # ─── TIER 4: Contractions ───────────────────────────────────────────────
    "contractions": [
        (re.compile(r"\bcannot\b", _I), "can't", 0),
        (re.compile(r"\bdo not\b"), "don't", 1),
        (re.compile(r"\bDo not\b"), "Don't", 1),
        (re.compile(r"\bdoes not\b", _I), "doesn't", 1),
        (re.compile(r"\bwill not\b", _I), "won't", 1),
        (re.compile(r"\bshould not\b", _I), "shouldn't", 1),
        (re.compile(r"\bwould not\b", _I), "wouldn't", 1),
        (re.compile(r"\bcould not\b", _I), "couldn't", 1),
        (re.compile(r"\bis not\b", _I), "isn't", 1),
        (re.compile(r"\bare not\b", _I), "aren't", 1),
        (re.compile(r"\bwas not\b", _I), "wasn't", 1),
        (re.compile(r"\bwere not\b", _I), "weren't", 1),
        (re.compile(r"\bhas not\b", _I), "hasn't", 1),
        (re.compile(r"\bhave not\b", _I), "haven't", 1),
        (re.compile(r"\bhad not\b", _I), "hadn't", 1),
        (re.compile(r"\bit is\b", _I), "it's", 1),
        (re.compile(r"\bthat is\b", _I), "that's", 1),
        (re.compile(r"\bthere is\b", _I), "there's", 1),
        (re.compile(r"\bthey are\b", _I), "they're", 1),
        (re.compile(r"\bwe are\b", _I), "we're", 1),
        (re.compile(r"\byou are\b", _I), "you're", 1),
        (re.compile(r"\bwe have\b", _I), "we've", 1),
        (re.compile(r"\bthey have\b", _I), "they've", 1),
        (re.compile(r"\byou have\b", _I), "you've", 1),
        (re.compile(r"\blet us\b", _I), "let's", 1),
    ],

    # ─── TIER 5: Structural ─────────────────────────────────────────────────
    "structural": [
        (re.compile(r"^[-*_]{5,}\s*$", re.MULTILINE), "---", 1),
        (re.compile(r"^(#{1,6})  +", re.MULTILINE), r"\1 ", 0),
        (re.compile(r"^(\s*[-*+])  +", re.MULTILINE), r"\1 ", 0),
        (re.compile(r'\[([^\]]+)\]\(([^)]+)\s+""\)'), r'[\1](\2)', 1),
        (re.compile(r"[ \t]+$", re.MULTILINE), "", 0),
        (re.compile(r"\n{3,}"), "\n\n", 1),
    ],
}

# Context-sensitive abbreviations: only apply when a trigger word is nearby
CONTEXT_ABBREVIATIONS = [
    {"word": re.compile(r"\bserver\b", _I),    "abbr": "srv",  "triggers": re.compile(r"\b(web|proxy|auth|mail|DNS|API|app|file|media)\b", _I)},
    {"word": re.compile(r"\bservers\b", _I),   "abbr": "srvs", "triggers": re.compile(r"\b(web|proxy|auth|mail|DNS|API|app|file|media)\b", _I)},
    {"word": re.compile(r"\bservices\b", _I),  "abbr": "svcs", "triggers": re.compile(r"\b(web|micro|auth|backend|API|cloud|worker)\b", _I)},
    {"word": re.compile(r"\bservice\b", _I),   "abbr": "svc",  "triggers": re.compile(r"\b(web|micro|auth|backend|API|cloud|worker)\b", _I)},
    {"word": re.compile(r"\bcontainers?\b", _I), "abbr": lambda m: "ctrs" if m.lower().endswith("s") else "ctr", "triggers": re.compile(r"\b(docker|pod|k8s|runtime|OCI)\b", _I)},
    {"word": re.compile(r"\bpackages?\b", _I),   "abbr": lambda m: "pkgs" if m.lower().endswith("s") else "pkg", "triggers": re.compile(r"\b(npm|pip|gem|maven|nuget|apt|brew)\b", _I)},
    {"word": re.compile(r"\bmessages?\b", _I),   "abbr": lambda m: "msgs" if m.lower().endswith("s") else "msg", "triggers": re.compile(r"\b(error|log|queue|event|status|alert)\b", _I)},
    {"word": re.compile(r"\bcommands?\b", _I),   "abbr": lambda m: "cmds" if m.lower().endswith("s") else "cmd", "triggers": re.compile(r"\b(run|exec|shell|bash|terminal|CLI)\b", _I)},
    {"word": re.compile(r"\bconnections?\b", _I),"abbr": lambda m: "conns" if m.lower().endswith("s") else "conn", "triggers": re.compile(r"\b(DB|database|socket|TCP|HTTP|pool)\b", _I)},
    {"word": re.compile(r"\bversions?\b", _I),   "abbr": lambda m: "vers" if m.lower().endswith("s") else "ver", "triggers": re.compile(r"\b(API|release|semantic|latest|current|minor|major|patch)\b", _I)},
    {"word": re.compile(r"\bnumber\b", _I),    "abbr": "num",  "triggers": re.compile(r"\b(phone|ID|sequence|port|max|min|total|count)\b", _I)},
    {"word": re.compile(r"\bstring\b", _I),    "abbr": "str",  "triggers": re.compile(r"\b(format|parse|concat|empty|query|JSON|input)\b", _I)},
    {"word": re.compile(r"\binteger\b", _I),   "abbr": "int",  "triggers": re.compile(r"\b(parse|signed|unsigned|32|64|big)\b", _I)},
    {"word": re.compile(r"\bboolean\b", _I),   "abbr": "bool", "triggers": re.compile(r"\b(flag|check|return|is|has|can)\b", _I)},
    {"word": re.compile(r"\bcharacters?\b", _I), "abbr": lambda m: "chars" if m.lower().endswith("s") else "char", "triggers": re.compile(r"\b(special|escape|unicode|ASCII|UTF|max|min)\b", _I)},
]

# Aggressive-only extra patterns
AGGRESSIVE_SYNONYMS = [
    (re.compile(r"\bis responsible for\b", _I), "handles", 2),
    (re.compile(r"\bare responsible for\b", _I), "handle", 2),
    (re.compile(r"\bresponsible for\b", _I), "handles", 1),
    (re.compile(r"\bin conjunction with\b", _I), "with", 2),
    (re.compile(r"\bon a per-(\w+) basis\b", _I), r"per \1", 2),
    (re.compile(r"\bwith the exception of\b", _I), "except", 3),
    (re.compile(r"\bin the process of (\w+)ing\b", _I), r"\1ing", 3),
    (re.compile(r"\bprovide support for\b", _I), "support", 2),
    (re.compile(r"\btake advantage of\b", _I), "use", 2),
    (re.compile(r"\bgive rise to\b", _I), "cause", 2),
    (re.compile(r"\bin the context of\b", _I), "in", 3),
    (re.compile(r"\bby means of\b", _I), "via", 2),
    (re.compile(r"\bin the vicinity of\b", _I), "near", 3),
    (re.compile(r"\bat the present time\b", _I), "now", 3),
    (re.compile(r"\bin the near future\b", _I), "soon", 3),
    (re.compile(r"\bat this point in time\b", _I), "now", 4),
    (re.compile(r"\bthe vast majority of\b", _I), "most", 3),
    (re.compile(r"\ba large number of\b", _I), "many", 3),
    (re.compile(r"\ba small number of\b", _I), "few", 3),
    (re.compile(r"\bthe ability to\b", _I), "can", 2),
    (re.compile(r"\bhave the ability to\b", _I), "can", 3),
    (re.compile(r"\bhas the ability to\b", _I), "can", 3),
    (re.compile(r"\bin the event that\b", _I), "if", 3),
    (re.compile(r"\bdue to the fact that\b", _I), "because", 4),
    (re.compile(r"\bin order to\b", _I), "to", 2),
    (re.compile(r"\bfor the purpose of\b", _I), "to", 3),
    (re.compile(r"\bwith the goal of\b", _I), "to", 3),
]


def apply_token_synonyms(text: str, level: str = "medium") -> tuple[str, dict]:
    """Apply tokenizer-aware synonym replacements. Returns (text, stats)."""
    use_technical = True
    use_symbols = level != "light"
    use_synonyms = level != "light"
    use_contractions = level == "aggressive"
    use_structural = True
    use_contextual = level == "aggressive"
    use_aggressive = level == "aggressive"

    replacements = 0
    estimated_saved = 0

    def apply_patterns(patterns: list) -> None:
        nonlocal text, replacements, estimated_saved
        for entry in patterns:
            pattern, replacement, savings = entry
            if savings == 0:
                continue
            before = text
            text = pattern.sub(replacement, text)
            if text != before:
                replacements += 1
                estimated_saved += savings

    if use_technical:    apply_patterns(TOKEN_SYNONYMS["technical"])
    if use_symbols:      apply_patterns(TOKEN_SYNONYMS["symbols"])
    if use_synonyms:     apply_patterns(TOKEN_SYNONYMS["synonyms"])
    if use_contractions: apply_patterns(TOKEN_SYNONYMS["contractions"])
    if use_structural:   apply_patterns(TOKEN_SYNONYMS["structural"])

    if use_contextual:
        for rule in CONTEXT_ABBREVIATIONS:
            word_pat = rule["word"]
            abbr = rule["abbr"]
            trigger_pat = rule["triggers"]
            text_snap = text  # snapshot for context window

            def _make_replacer(snap: str, a, trig):
                def _replacer(m: re.Match) -> str:
                    start = max(0, m.start() - 120)
                    end = min(len(snap), m.end() + 120)
                    context = snap[start:end]
                    if trig.search(context):
                        nonlocal replacements, estimated_saved
                        replacements += 1
                        estimated_saved += 1
                        return a(m.group(0)) if callable(a) else a
                    return m.group(0)
                return _replacer

            text = word_pat.sub(_make_replacer(text_snap, abbr, trigger_pat), text)

    if use_aggressive:
        apply_patterns(AGGRESSIVE_SYNONYMS)

    return text, {"replacements": replacements, "estimated_tokens_saved": estimated_saved}
