import datetime as dt
import logging
import tempfile
import unittest
from pathlib import Path
from unittest.mock import patch

from phs.core.config import Config
from phs.core.database import Database
from phs.core.module import Context
from phs.core.tailer import StatefulTail
from phs.modules.mail import MailModule


class DummyNotifier:
    def __init__(self):
        self.sent = []

    def send(self, subject, body):
        self.sent.append((subject, body))
        return True


class MailThresholdTests(unittest.TestCase):
    def _line(self, number):
        now = dt.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        return (
            f"{now} 1test-{number:06d}-XYZ <= ventas@example.com "
            "H=client [203.0.113.10]:50000 P=esmtpsa "
            "A=dovecot_login:ventas@example.com S=1234\n"
        )

    def test_warn_then_suspend(self):
        with tempfile.TemporaryDirectory() as directory:
            root = Path(directory)
            exim = root / "exim_mainlog"
            config_path = root / "config.ini"
            config_path.write_text(
                f"""[general]
notification_email=alerts@example.net
check_interval=60
database={root / 'security.sqlite3'}
log_file={root / 'security.log'}
state_dir={root / 'state'}
quarantine_dir={root / 'quarantine'}
hostname=test.example
[mail]
exim_log={exim}
warning_limit=100
suspend_limit=500
window_seconds=3600
auto_suspend=yes
repeat_warning_seconds=3600
retry_suspend_seconds=900
""",
                encoding="utf-8",
            )
            exim.write_text("".join(self._line(i) for i in range(101)), encoding="utf-8")
            config = Config(config_path)
            database = Database(config.database_path)
            logger = logging.getLogger("mail-test")
            notifier = DummyNotifier()
            tailer = StatefulTail(database, logger)
            module = MailModule(Context(config, database, logger, notifier, tailer))

            with patch("phs.modules.mail.CPanel.users", return_value={"cpuser"}), patch(
                "phs.modules.mail.CPanel.domain_owners", return_value={"example.com": "cpuser"}
            ), patch("phs.modules.mail.CPanel.uapi", return_value=(True, '{"result":{"status":1}}')) as uapi:
                module.run()
                self.assertEqual(len(notifier.sent), 1)
                self.assertIn("[ALERTA]", notifier.sent[0][0])
                self.assertFalse(uapi.called)

                with exim.open("a", encoding="utf-8") as handle:
                    handle.write("".join(self._line(i) for i in range(101, 501)))
                module.run()
                self.assertTrue(uapi.called)
                self.assertEqual(uapi.call_args.args[:3], ("cpuser", "Email", "suspend_outgoing"))
                self.assertEqual(uapi.call_args.kwargs["email"], "ventas@example.com")
                self.assertTrue(any("[SUSPENDIDO]" in subject for subject, _ in notifier.sent))

            database.close()


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