# Docs: /guides/send-cold-email-python
import tempfile
import unittest
from pathlib import Path
from outreach import open_state, tick, apply_event, scenario


class OutreachTests(unittest.TestCase):
    def test_pacing_cancellation_and_dedupe(self):
        db = open_state(":memory:")
        try:
            self.assertEqual(tick(db, 0)["email"], "ada@example.com")
            self.assertIsNone(tick(db, 59))
            for now in (60, 120, 180):
                tick(db, now)
            for event in (("r", "ada@example.com", "reply"), ("o", "bo@example.com", "opt-out"), ("b", "cy@example.com", "bounce")):
                self.assertTrue(apply_event(db, *event))
                self.assertFalse(apply_event(db, *event))
                self.assertEqual(db.execute("SELECT status FROM jobs WHERE email=? AND step=1", (event[1],)).fetchone()[0], "canceled")
            self.assertEqual(tick(db, 86580)["email"], "dev@example.com")
            self.assertIsNone(tick(db, 86640))
            self.assertEqual(db.execute("SELECT COUNT(*) FROM attempts").fetchone()[0], 5)
        finally:
            db.close()

    def test_restart_checkpoint(self):
        with tempfile.TemporaryDirectory() as directory:
            path = str(Path(directory) / "state.sqlite")
            db = open_state(path)
            first = scenario(db)
            db.close()
            db = open_state(path)
            try:
                self.assertEqual(scenario(db), first)
                self.assertEqual(first["events"], 3)
                self.assertEqual(first["canceled"], 3)
                self.assertEqual(first["attempts"], 5)
            finally:
                db.close()

    def test_untrusted_mapping_rejected(self):
        db = open_state(":memory:")
        try:
            with self.assertRaisesRegex(ValueError, "Unknown"):
                apply_event(db, "x", "other@example.com", "reply")
            with self.assertRaisesRegex(ValueError, "Invalid"):
                apply_event(db, "x", "ada@example.com", "open")
            self.assertEqual(db.execute("SELECT COUNT(*) FROM events").fetchone()[0], 0)
        finally:
            db.close()


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