"""Enrollment lifecycle tests for sequence send progression."""

from __future__ import annotations

import tempfile
import unittest
from datetime import datetime, timedelta

from kiessclaw.agents.sequencer_agent import KiessSequencerAgent
from kiessclaw.core.memory import MemoryEngine
from kiessclaw.models.contact import Contact

from tests.test_helpers import base_config


class EnrollmentLifecycleTest(unittest.TestCase):
    """Validate enrollment progression from step 1 to completion."""

    def test_enrollment_advances_and_completes(self) -> None:
        """Send runs should advance steps and finish sequence at final step."""
        with tempfile.TemporaryDirectory() as tempdir:
            memory = MemoryEngine(tempdir)
            agent = KiessSequencerAgent(base_config(), memory)

            # Prevent real SMTP calls in tests.
            agent.email_skill.send_email = lambda **_: {
                "success": True,
                "message_id": f"msg-{int(datetime.now().timestamp() * 1000)}",
                "error": None,
            }

            contact = Contact(
                email="flow@test.com",
                first_name="Flow",
                last_name="Tester",
                title="Head of Sales",
            )
            sequence = agent.sequence_skill.create_sequence(
                name="Lifecycle Seq",
                sender_email="rep@test.com",
                steps=[
                    {"channel": "email", "delay_days": 0, "subject": "S1", "body": "Body 1"},
                    {"channel": "email", "delay_days": 0, "subject": "S2", "body": "Body 2"},
                ],
            )
            sequence["status"] = "active"
            enrollment = agent.sequence_skill.enroll_contact(sequence["id"], contact.id, start_immediately=True)
            enrollment["next_send_at"] = (datetime.now() - timedelta(minutes=2)).isoformat()

            memory.save_data("contacts", [contact.to_dict()])
            memory.save_data("sequences", [sequence])
            memory.save_data("enrollments", [enrollment])
            memory.save_data("messages", [])

            first_run = agent.run("send", dry_run=False, limit=10)
            self.assertIn("Sent", first_run)

            enrollments_after_first = memory.load_data("enrollments")
            self.assertEqual(2, enrollments_after_first[0]["current_step"])
            self.assertEqual("active", enrollments_after_first[0]["status"])

            # Force second step to be due now.
            enrollments_after_first[0]["next_send_at"] = (datetime.now() - timedelta(minutes=1)).isoformat()
            memory.save_data("enrollments", enrollments_after_first)

            second_run = agent.run("send", dry_run=False, limit=10)
            self.assertIn("Sent", second_run)

            enrollments_after_second = memory.load_data("enrollments")
            messages = memory.load_data("messages")
            self.assertEqual("completed", enrollments_after_second[0]["status"])
            self.assertIsNone(enrollments_after_second[0]["next_send_at"])
            self.assertEqual(2, len(messages))


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