"""Tests for the scheduled-email package."""

from __future__ import annotations

from unittest.mock import MagicMock, patch
from urllib.parse import unquote

import pytest

from scheduled_email._config import ScheduledEmailConfig
from scheduled_email._core import build_login_url, generate_secret
from scheduled_email._scheduler import ScheduledEmailService


class TestGenerateSecret:
    def test_length(self) -> None:
        secret = generate_secret()
        assert len(secret) >= 32

    def test_uniqueness(self) -> None:
        secrets = {generate_secret() for _ in range(20)}
        assert len(secrets) == 20


class TestBuildLoginUrl:
    def test_starts_with_base_url(self) -> None:
        base = "https://example.com/login?token="
        url = build_login_url(base, "test-secret")
        assert url.startswith(base)

    def test_hash_is_url_safe(self) -> None:
        url = build_login_url("https://x.com/?t=", "s")
        hash_part = url.split("?t=", 1)[1]
        assert "$" not in hash_part
        assert unquote(hash_part).startswith("$argon2")


class TestScheduledEmailConfigValidate:
    def test_raises_when_smtp_user_empty(self) -> None:
        cfg = ScheduledEmailConfig(smtp_user="", smtp_pass="p", recipient="r@e.com")
        with pytest.raises(ValueError, match="SCHEDMAIL_SMTP_USER"):
            cfg.validate()

    def test_raises_when_smtp_pass_empty(self) -> None:
        cfg = ScheduledEmailConfig(smtp_user="u@e.com", smtp_pass="", recipient="r@e.com")
        with pytest.raises(ValueError, match="SCHEDMAIL_SMTP_PASS"):
            cfg.validate()

    def test_raises_when_recipient_empty(self) -> None:
        cfg = ScheduledEmailConfig(smtp_user="u@e.com", smtp_pass="p", recipient="")
        with pytest.raises(ValueError, match="SCHEDMAIL_RECIPIENT"):
            cfg.validate()

    def test_passes_when_all_set(self) -> None:
        cfg = ScheduledEmailConfig(smtp_user="u@e.com", smtp_pass="p", recipient="r@e.com")
        cfg.validate()


class TestScheduledEmailServiceStartStop:
    @patch("scheduled_email._mailer.smtplib.SMTP_SSL")
    def test_start_sends_email_and_sets_url(self, mock_ssl_cls: MagicMock) -> None:
        mock_srv = MagicMock()
        mock_ssl_cls.return_value.__enter__ = MagicMock(return_value=mock_srv)
        mock_ssl_cls.return_value.__exit__ = MagicMock(return_value=False)

        cfg = ScheduledEmailConfig(
            smtp_user="u@e.com",
            smtp_pass="pass",
            recipient="r@e.com",
            base_url="https://example.com/login?token=",
        )
        svc = ScheduledEmailService(cfg)
        svc.start()

        mock_srv.login.assert_called_once_with("u@e.com", "pass")
        mock_srv.sendmail.assert_called_once()
        assert svc.current_url is not None
        assert svc.current_url.startswith("https://example.com/login?token=")

        svc.stop()
        assert svc._timer is None
