"""Tests for variables.py."""

import pytest
from rtisanepy import (
    Unit, Participant, Time,
    Continuous, Counts, UnorderedCategories, OrderedCategories,
    continuous, counts, categories,
    Exactly, AtMost, Per,
)


class TestUnit:
    def test_basic_creation(self):
        u = Unit("student", cardinality=100)
        assert u.name == "student"
        assert u.cardinality == 100
        assert u.nests_within is None

    def test_nesting(self):
        classroom = Unit("classroom", cardinality=10)
        student = Unit("student", cardinality=100, nests_within=classroom)
        assert student.nests_within is classroom

    def test_nesting_list(self):
        school = Unit("school", cardinality=5)
        classroom = Unit("classroom", cardinality=10)
        student = Unit("student", cardinality=100, nests_within=[classroom, school])
        assert student.nests_within == [classroom, school]


class TestParticipant:
    def test_is_unit_alias(self):
        p = Participant("student", cardinality=100)
        assert isinstance(p, Unit)
        assert p.name == "student"


class TestTime:
    def test_with_order(self):
        t = Time("week", order=["w1", "w2", "w3"])
        assert t.cardinality == 3

    def test_with_cardinality(self):
        t = Time("trial", cardinality=5)
        assert t.cardinality == 5

    def test_requires_order_or_cardinality(self):
        with pytest.raises(ValueError):
            Time("t")

    def test_mismatch_raises(self):
        with pytest.raises(ValueError):
            Time("t", order=["a", "b"], cardinality=3)


class TestMeasureConstructors:
    def test_continuous(self):
        u = Unit("s", cardinality=10)
        m = continuous(u, "Score")
        assert isinstance(m, Continuous)
        assert m.name == "Score"
        assert m.unit is u
        assert m.number_of_instances == 1

    def test_counts(self):
        u = Unit("s", cardinality=10)
        m = counts(u, "NumEvents")
        assert isinstance(m, Counts)

    def test_categories_unordered(self):
        u = Unit("s", cardinality=10)
        m = categories(u, "Color", cardinality=3)
        assert isinstance(m, UnorderedCategories)
        assert m.cardinality == 3

    def test_categories_ordered(self):
        u = Unit("s", cardinality=10)
        m = categories(u, "SES", order=["low", "mid", "high"])
        assert isinstance(m, OrderedCategories)
        assert m.cardinality == 3
        assert m.order == ["low", "mid", "high"]

    def test_categories_requires_cardinality_or_order(self):
        u = Unit("s", cardinality=10)
        with pytest.raises(ValueError):
            categories(u, "X")


class TestNumberHelpers:
    def test_exactly(self):
        e = Exactly(3)
        assert e.value == 3

    def test_atmost(self):
        a = AtMost(5)
        assert a.value == 5

    def test_per(self):
        u = Unit("s", cardinality=10)
        t = Time("week", cardinality=4)
        p = Per(number=Exactly(1), variable=t)
        assert p.number.value == 1
        assert p.variable is t

    def test_number_of_instances_with_per(self):
        u = Unit("s", cardinality=10)
        t = Time("week", cardinality=4)
        m = continuous(u, "Score", number_of_instances=Per(number=2, variable=t))
        assert isinstance(m.number_of_instances, Per)
