#!/usr/bin/env python3
"""
Helix Grammar v3 - CDR-Unified Codon Semantics

This module unifies Helix64 codon semantics with CDR_Steven_Package's
canonical programs.py definitions. It eliminates legacy vm_op mappings
in favor of pure semantic roles.

Key improvements over v2:
    - Imports canonical codon tables from CDR programs.py
    - Removes vm_op legacy shim (deprecated, kept as alias)
    - Adds gate_mutation helper functions
    - Provides single source of truth for Helix8 pipeline semantics

Usage:
    from helix_cdc.helix_grammar_v3 import (
        CODON_SEMANTICS,
        POSITION_SEMANTICS,
        GATE_POLICIES,
        mutate_gate,
        describe_program,
    )
"""

from __future__ import annotations

import os
import sys
import warnings
from typing import Dict, List, Optional, Set, Tuple

# Attempt to import from CDR package for canonical definitions
CDR_ROOT = os.environ.get("CDR_ROOT", "/home/voidstr3m33/CDR_Steven_Package")
CDR_PROGRAMS_PATH = os.path.join(CDR_ROOT, "code", "bloomos")

_CDR_AVAILABLE = False
try:
    if CDR_PROGRAMS_PATH not in sys.path:
        sys.path.insert(0, CDR_PROGRAMS_PATH)
    from programs import (
        HELIX8_POSITIONS,
        LETTER_TO_OP,
        OP_TO_LETTER,
        GATE_POSITION,
        GATE_SEMANTICS,
        BASE_PROGRAM,
    )
    _CDR_AVAILABLE = True
except ImportError:
    # Fallback to inline definitions if CDR not available
    _CDR_AVAILABLE = False
    HELIX8_POSITIONS = [
        "CTX_GATHER",      # 0 - A
        "EMBED",           # 1 - B
        "PROJ_UP",         # 2 - C
        "LAYER_NORM",      # 3 - D
        "BIAS_RELU",       # 4 - E (GATE)
        "W1_MATMUL",       # 5 - F
        "SOFTMAX",         # 6 - G
        "EMIT_LOGITS",     # 7 - H
    ]
    LETTER_TO_OP = {
        "A": "CTX_GATHER",
        "B": "EMBED",
        "C": "PROJ_UP",
        "D": "LAYER_NORM",
        "E": "BIAS_RELU",
        "F": "W1_MATMUL",
        "G": "SOFTMAX",
        "H": "EMIT_LOGITS",
    }
    OP_TO_LETTER = {v: k for k, v in LETTER_TO_OP.items()}
    GATE_POSITION = 4
    BASE_PROGRAM = "ABCDEFGH"
    GATE_SEMANTICS = {
        "math_bias": {
            "mutation": "E→G",
            "program": "ABCDGFGH",
            "effect": "Softmax at gate position",
        },
        "code_bias": {
            "mutation": "E→A",
            "program": "ABCDAFGH",
            "effect": "CTX_GATHER at gate position",
        },
        "json_bias": {
            "mutation": "E→B",
            "program": "ABCDBFGH",
            "effect": "EMBED at gate position",
        },
        "balanced": {
            "mutation": "E→E",
            "program": "ABCDEFGH",
            "effect": "No mutation (baseline)",
        },
    }


# ============================================================================
# CANONICAL CODON SEMANTICS (v3 - Pure semantic roles, no vm_op)
# ============================================================================

CODONS = list("ABCDEFGH")
PROGRAM_LENGTH = 8
CANONICAL_PROGRAM = BASE_PROGRAM

# Semantic meaning of each codon
CODON_SEMANTICS: Dict[str, Dict] = {
    "A": {
        "name": "CTX_GATHER",
        "description": "Gather context from input stream",
        "cdr_role": "Symbol ingestion and context preparation",
        # Deprecated vm_op alias - kept for backward compatibility
        "vm_op": "INIT",  # DEPRECATED
    },
    "B": {
        "name": "EMBED",
        "description": "Project input into embedding space",
        "cdr_role": "Map symbols to dense representations",
        "vm_op": "LOAD_W1",  # DEPRECATED
    },
    "C": {
        "name": "PROJ_UP",
        "description": "Project embeddings to higher dimension",
        "cdr_role": "Expand representational capacity",
        "vm_op": "LOAD_B1",  # DEPRECATED
    },
    "D": {
        "name": "LAYER_NORM",
        "description": "Normalize activations for stability",
        "cdr_role": "Stabilize information flow",
        "vm_op": "MATMUL_1",  # DEPRECATED
    },
    "E": {
        "name": "BIAS_RELU",
        "description": "Bias + ReLU activation (ANCHOR GATE)",
        "cdr_role": "Gate position - controls information flow",
        "is_gate": True,
        "vm_op": "ADD_BIAS_1",  # DEPRECATED
    },
    "F": {
        "name": "W1_MATMUL",
        "description": "First weight matrix multiply",
        "cdr_role": "Transform through learned weights",
        "vm_op": "LOAD_W2",  # DEPRECATED
    },
    "G": {
        "name": "SOFTMAX",
        "description": "Apply softmax for probability distribution",
        "cdr_role": "Normalize to probability space",
        "vm_op": "MATMUL_2",  # DEPRECATED
    },
    "H": {
        "name": "EMIT_LOGITS",
        "description": "Emit final logits/output",
        "cdr_role": "Return result to caller",
        "vm_op": "OUTPUT",  # DEPRECATED
    },
}

# Position semantics
POSITION_SEMANTICS: Dict[int, Dict] = {
    0: {"codon": "A", "role": "context_gather", "phase": "input"},
    1: {"codon": "B", "role": "embedding", "phase": "encode"},
    2: {"codon": "C", "role": "projection_up", "phase": "encode"},
    3: {"codon": "D", "role": "layer_norm", "phase": "transform"},
    4: {"codon": "E", "role": "anchor_gate", "phase": "gate", "is_tunable": True},
    5: {"codon": "F", "role": "w1_matmul", "phase": "transform"},
    6: {"codon": "G", "role": "softmax", "phase": "output"},
    7: {"codon": "H", "role": "emit_logits", "phase": "output"},
}

# Gate policies from CDR
GATE_POLICIES = GATE_SEMANTICS


# ============================================================================
# GATE MUTATION FUNCTIONS
# ============================================================================

def mutate_gate(program: str, policy: str) -> str:
    """
    Apply a gate mutation policy to a Helix8 program.

    Args:
        program: Base program (e.g., "ABCDEFGH")
        policy: Gate policy name ("math_bias", "code_bias", "json_bias", "balanced")

    Returns:
        Mutated program string

    Example:
        >>> mutate_gate("ABCDEFGH", "math_bias")
        'ABCDGFGH'
    """
    if policy not in GATE_POLICIES:
        return program

    policy_info = GATE_POLICIES[policy]
    return policy_info.get("program", program)


def get_gate_codon(policy: str) -> str:
    """
    Get the codon used at gate position for a policy.

    Args:
        policy: Gate policy name

    Returns:
        Single codon character
    """
    if policy not in GATE_POLICIES:
        return "E"  # Default gate codon

    mutated = GATE_POLICIES[policy].get("program", CANONICAL_PROGRAM)
    if len(mutated) > GATE_POSITION:
        return mutated[GATE_POSITION]
    return "E"


def infer_gate_policy(program: str) -> str:
    """
    Infer the gate policy from a program string.

    Args:
        program: Program string (e.g., "ABCDGFGH")

    Returns:
        Policy name or "custom" if not matching known policies
    """
    for policy_name, policy_info in GATE_POLICIES.items():
        if policy_info.get("program") == program:
            return policy_name
    return "custom"


# ============================================================================
# VALIDATION AND DESCRIPTION
# ============================================================================

def is_valid_sequence(seq: str) -> bool:
    """Check if a program sequence is valid (8 chars, A-H only)."""
    if not isinstance(seq, str) or len(seq) != PROGRAM_LENGTH:
        return False
    return all(c in CODONS for c in seq)


def validate_sequence(seq: str) -> List[str]:
    """Validate a sequence and return list of errors."""
    errors = []
    if not isinstance(seq, str):
        errors.append(f"Sequence must be string, got {type(seq).__name__}")
        return errors
    if len(seq) != PROGRAM_LENGTH:
        errors.append(f"Sequence must be {PROGRAM_LENGTH} chars, got {len(seq)}")
        return errors
    for i, c in enumerate(seq):
        if c not in CODONS:
            errors.append(f"Position {i}: '{c}' not valid (must be A-H)")
    return errors


def describe_program(seq: str) -> str:
    """
    Generate human-readable description of a Helix8 program.

    Args:
        seq: Program sequence

    Returns:
        Multi-line description string
    """
    lines = [f"Program: {seq}"]

    policy = infer_gate_policy(seq)
    lines.append(f"Gate Policy: {policy}")
    lines.append("")
    lines.append("Pipeline:")

    for i, c in enumerate(seq):
        codon_info = CODON_SEMANTICS.get(c, {})
        name = codon_info.get("name", c)
        role = codon_info.get("cdr_role", "")
        gate_marker = " <- GATE" if i == GATE_POSITION else ""

        lines.append(f"  [{i}] {c} ({name}): {role}{gate_marker}")

    errors = validate_sequence(seq)
    if errors:
        lines.append("")
        lines.append("Errors:")
        for e in errors:
            lines.append(f"  - {e}")

    return "\n".join(lines)


def program_to_ops(program: str) -> List[str]:
    """Convert letter program to semantic operation list."""
    return [LETTER_TO_OP.get(c, f"UNKNOWN_{c}") for c in program]


def ops_to_program(ops: List[str]) -> str:
    """Convert semantic operation list to letter program."""
    return "".join(OP_TO_LETTER.get(op, "?") for op in ops)


# ============================================================================
# DEPRECATION WARNINGS FOR vm_op
# ============================================================================

def get_vm_op(codon: str) -> str:
    """
    Get the legacy vm_op for a codon.

    DEPRECATED: Use CODON_SEMANTICS[codon]["name"] instead.
    """
    warnings.warn(
        "get_vm_op() is deprecated. Use CODON_SEMANTICS[codon]['name'] instead.",
        DeprecationWarning,
        stacklevel=2,
    )
    info = CODON_SEMANTICS.get(codon, {})
    return info.get("vm_op", "UNKNOWN")


# ============================================================================
# MODULE INFO
# ============================================================================

def grammar_info() -> Dict:
    """Get grammar module information."""
    return {
        "version": "v3",
        "cdr_available": _CDR_AVAILABLE,
        "cdr_root": CDR_ROOT,
        "codons": CODONS,
        "program_length": PROGRAM_LENGTH,
        "canonical_program": CANONICAL_PROGRAM,
        "gate_position": GATE_POSITION,
        "gate_policies": list(GATE_POLICIES.keys()),
    }


# CLI / Self-test
if __name__ == "__main__":
    print("=== Helix Grammar v3 - CDR Unified ===\n")

    info = grammar_info()
    for k, v in info.items():
        print(f"  {k}: {v}")
    print()

    print("Gate Policies:")
    for name, policy in GATE_POLICIES.items():
        prog = policy.get("program", "?")
        effect = policy.get("effect", "?")
        print(f"  {name}: {prog} ({effect})")
    print()

    print("Program Descriptions:")
    for prog in ["ABCDEFGH", "ABCDGFGH", "ABCDAFGH", "ABCDBFGH"]:
        print(describe_program(prog))
        print("-" * 50)
