#!/usr/bin/env python3
"""Deterministic data-contract and distribution-drift learning example."""

from __future__ import annotations

import math


REFERENCE = [
    {"entity_id": f"r{i}", "score": score}
    for i, score in enumerate([0.10, 0.20, 0.25, 0.30, 0.35, 0.40, 0.60, 0.70, 0.80, 0.90])
]
CURRENT = [
    {"entity_id": f"c{i}", "score": score}
    for i, score in enumerate([0.10, 0.40, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90])
]


def validate(rows: list[dict[str, object]], name: str) -> None:
    required = {"entity_id", "score"}
    if not rows:
        raise ValueError(f"{name}: empty dataset")
    if any(set(row) != required for row in rows):
        raise ValueError(f"{name}: schema mismatch")
    ids = [row["entity_id"] for row in rows]
    if len(ids) != len(set(ids)):
        raise ValueError(f"{name}: duplicate entity_id")
    if any(not isinstance(row["score"], (int, float)) or not 0 <= row["score"] <= 1 for row in rows):
        raise ValueError(f"{name}: score outside [0, 1]")
    print(f"Contract {name}: PASS ({len(rows)} rows)")


def proportions(rows: list[dict[str, object]]) -> list[float]:
    low = sum(float(row["score"]) < 0.5 for row in rows)
    return [low / len(rows), (len(rows) - low) / len(rows)]


def psi(reference: list[float], current: list[float]) -> float:
    if any(value <= 0 for value in reference + current):
        raise ValueError("All bins need positive mass for this simple PSI example")
    return sum((new - old) * math.log(new / old) for old, new in zip(reference, current))


def main() -> None:
    validate(REFERENCE, "reference")
    validate(CURRENT, "current")
    reference_bins = proportions(REFERENCE)
    current_bins = proportions(CURRENT)
    score = psi(reference_bins, current_bins)
    print(f"Reference bins: {reference_bins}")
    print(f"Current bins: {current_bins}")
    print(f"PSI: {score:.6f}")
    print("Triage: distribution alert; performance impact unknown without labels")


if __name__ == "__main__":
    main()
