"""Synthetic score gate, standard library only. No models or network calls."""
import json
import math
import sys
import unittest

THRESHOLD = 0.8


def naive_gate(raw):
    score = json.loads(raw)["score"]
    if score < THRESHOLD:
        return "FAIL"
    return "PASS"


def reject_constant(token):
    raise ValueError("non-standard numeric constant: " + token)


def unique_object(pairs):
    result = {}
    for key, value in pairs:
        if key in result:
            raise ValueError("duplicate member")
        result[key] = value
    return result


def read_score(raw):
    record = json.loads(raw, parse_constant=reject_constant,
                        object_pairs_hook=unique_object)
    if type(record) is not dict or set(record) != {"score"}:
        raise ValueError("expected one score field")
    score = record["score"]
    if type(score) not in (int, float):
        raise ValueError("score must be numeric, excluding bool")
    # Check float finiteness without converting an arbitrary-size integer.
    if type(score) is float and not math.isfinite(score):
        raise ValueError("score must be finite")
    if not 0 <= score <= 1:
        raise ValueError("score outside [0, 1]")
    return score


def strict_gate(raw):
    try:
        score = read_score(raw)
    except (ValueError, TypeError):
        return "INVALID"
    return "PASS" if score >= THRESHOLD else "FAIL"


class GateTests(unittest.TestCase):
    def test_naive_nan_passes(self):
        self.assertEqual(naive_gate('{"score":NaN}'), "PASS")

    def test_nan_comparisons(self):
        value = float("nan")
        self.assertFalse(value < THRESHOLD)
        self.assertFalse(value >= THRESHOLD)

    def test_constants_rejected(self):
        for token in ("NaN", "Infinity", "-Infinity"):
            with self.subTest(token=token):
                self.assertEqual(strict_gate('{"score":' + token + '}'), "INVALID")

    def test_exponent_overflow(self):
        raw = '{"score":1e400}'
        value = json.loads(raw, parse_constant=reject_constant)["score"]
        self.assertTrue(math.isinf(value))
        self.assertEqual(strict_gate(raw), "INVALID")

    def test_threshold(self):
        self.assertEqual(strict_gate('{"score":0.8}'), "PASS")
        self.assertEqual(strict_gate('{"score":0.799}'), "FAIL")

    def test_endpoints(self):
        self.assertEqual(strict_gate('{"score":0}'), "FAIL")
        self.assertEqual(strict_gate('{"score":1}'), "PASS")

    def test_out_of_range(self):
        for value in (-0.1, 1.1, 10**100):
            self.assertEqual(strict_gate(json.dumps({"score": value})), "INVALID")

    def test_wrong_types(self):
        for value in (True, False, None, "0.9", [], {}):
            self.assertEqual(strict_gate(json.dumps({"score": value})), "INVALID")

    def test_record_shape(self):
        for raw in ('{}', '[]', 'null', '{"score":0.9,"extra":0}'):
            self.assertEqual(strict_gate(raw), "INVALID")

    def test_duplicate_score(self):
        self.assertEqual(strict_gate('{"score":0.1,"score":0.9}'), "INVALID")

    def test_malformed(self):
        self.assertEqual(strict_gate('{"score":}'), "INVALID")

    def test_output_encoder(self):
        with self.assertRaises(ValueError):
            json.dumps({"score": float("nan")}, allow_nan=False)


if __name__ == "__main__":
    if "--test" in sys.argv:
        unittest.main(argv=[sys.argv[0]], verbosity=2)
    else:
        for raw in ('{"score":NaN}', '{"score":1e400}', '{"score":0.9}', '{"score":0.7}'):
            print(raw + " -> naive=" + naive_gate(raw) + ", strict=" + strict_gate(raw))
