import unittest

from aria_router.lifecycle import (
    JobLifecycle,
    JobStatus,
    InvalidTransition,
)
from aria_router.adapter_contract import (
    ExecutionPolicy,
    AdapterContractError,
)


class LifecycleTests(unittest.TestCase):

    def test_successful_lifecycle(self):
        job = JobLifecycle("job-1")

        job.transition(JobStatus.ROUTED)
        job.transition(JobStatus.RUNNING)
        job.transition(JobStatus.COMPLETED)

        self.assertEqual(
            job.status, JobStatus.COMPLETED
        )
        self.assertIsNotNone(job.finished_at)

    def test_blocked_job(self):
        job = JobLifecycle("job-2")

        job.transition(JobStatus.BLOCKED)

        self.assertEqual(
            job.status, JobStatus.BLOCKED
        )

    def test_completed_cannot_restart(self):
        job = JobLifecycle("job-3")

        job.transition(JobStatus.ROUTED)
        job.transition(JobStatus.RUNNING)
        job.transition(JobStatus.COMPLETED)

        with self.assertRaises(InvalidTransition):
            job.transition(JobStatus.RUNNING)

    def test_invalid_direct_completion(self):
        job = JobLifecycle("job-4")

        with self.assertRaises(InvalidTransition):
            job.transition(JobStatus.COMPLETED)

    def test_timeout_policy(self):
        policy = ExecutionPolicy(
            timeout_seconds=120
        )

        self.assertEqual(
            policy.timeout_seconds, 120
        )

    def test_invalid_timeout(self):
        with self.assertRaises(AdapterContractError):
            ExecutionPolicy(timeout_seconds=0)

    def test_retries_disabled(self):
        with self.assertRaises(AdapterContractError):
            ExecutionPolicy(max_attempts=3)

    def test_side_effects_disabled(self):
        with self.assertRaises(AdapterContractError):
            ExecutionPolicy(allow_side_effects=True)


if __name__ == "__main__":
    unittest.main()
