#!/usr/bin/env python3
"""PIST 8×8 strand adjacency matrix builder.

This is a raw-feature shim: it carries no admissibility logic. It tokenizes
input text, assigns each token to a strand by vocab_index % 8, and counts
bigram adjacencies projected onto strands.

Output schema matches `rrc_pist_predictions_250_v1.json` (matrix-only).
"""

from __future__ import annotations

import argparse
import hashlib
import json
import re
from typing import Any


def tokenize(text: str) -> list[str]:
    """Split text into normalized tokens."""
    text = text.lower()
    # Keep letters, digits, and a small set of math symbols
    tokens = re.findall(r"[a-z0-9]+|[+\-*/=^(){}\[\]]", text)
    return tokens


def strand(token: str, vocab: list[str]) -> int:
    return vocab.index(token) % 8


def build_matrix(tokens: list[str]) -> list[list[int]]:
    """Build 8×8 strand adjacency matrix from token bigrams."""
    vocab = sorted(set(tokens))
    matrix = [[0 for _ in range(8)] for _ in range(8)]
    for t_i, t_j in zip(tokens, tokens[1:]):
        matrix[strand(t_i, vocab)][strand(t_j, vocab)] += 1
    return matrix


def canonical_json_matrix(matrix: list[list[int]]) -> str:
    """Canonical row-major JSON with no whitespace for hashing."""
    return json.dumps(matrix, separators=(",", ":"))


def build_record(text: str, equation_id: str, name: str) -> dict[str, Any]:
    tokens = tokenize(text)
    vocab = sorted(set(tokens))
    matrix = build_matrix(tokens)
    matrix_json = canonical_json_matrix(matrix)
    return {
        "equation_id": equation_id,
        "name": name,
        "schema": "rrc_pist_predictions_250_v1",
        "claim_boundary": "matrix-only;no-classifier;no-lean-spectral",
        "matrix_schema": "token_strand_adjacency_8x8_v1",
        "matrix_8x8": matrix,
        "matrix_hash": hashlib.sha256(matrix_json.encode("utf-8")).hexdigest(),
        "global_vocab_hash": hashlib.sha256(
            json.dumps(vocab, separators=(",", ":")).encode("utf-8")
        ).hexdigest(),
        "proxy_pred": None,
        "exact_pred": None,
        "source_records": [{"equation_record_id": equation_id, "name": name}],
    }


def main() -> None:
    parser = argparse.ArgumentParser(description="Build PIST 8×8 adjacency matrix")
    parser.add_argument("--text", required=True, help="input equation text")
    parser.add_argument("--equation-id", default="rrc_eq_unknown")
    parser.add_argument("--name", default="unknown")
    parser.add_argument("--output", help="write JSON record to file")
    args = parser.parse_args()

    record = build_record(args.text, args.equation_id, args.name)
    out = json.dumps(record, indent=2)
    if args.output:
        with open(args.output, "w", encoding="utf-8") as f:
            f.write(out + "\n")
    else:
        print(out)


if __name__ == "__main__":
    main()
