"""Periodic key rotation via threading.Timer."""

from __future__ import annotations

import threading
from datetime import datetime, timezone

from ._config import ScheduledEmailConfig
from ._core import build_login_url, generate_secret
from ._mailer import send_notification


class ScheduledEmailService:
    """Generates a random secret, builds a login URL, sends it via email,
    then repeats every *rotate_hours* hours.
    """

    def __init__(self, cfg: ScheduledEmailConfig | None = None) -> None:
        self._cfg = cfg or ScheduledEmailConfig()
        self._timer: threading.Timer | None = None
        self._lock = threading.Lock()
        self._running = False
        self.current_secret: str | None = None
        self.current_url: str | None = None

    @property
    def config(self) -> ScheduledEmailConfig:
        return self._cfg

    def _rotate(self) -> None:
        """Generate a new secret, build the URL, send email, schedule next."""
        with self._lock:
            self.current_secret = generate_secret()
            self.current_url = build_login_url(self._cfg.base_url, self.current_secret)
            rotate_at = datetime.now(timezone.utc)

        try:
            send_notification(
                self._cfg,
                login_url=self.current_url,
                raw_secret=self.current_secret,
                rotate_at=rotate_at,
            )
        except Exception:
            pass

        self._schedule_next()

    def _schedule_next(self) -> None:
        if not self._running:
            return
        interval = self._cfg.rotate_hours * 3600
        self._timer = threading.Timer(interval, self._rotate)
        self._timer.daemon = True
        self._timer.start()

    def start(self) -> None:
        """Start the service: immediately rotate once, then schedule periodic.

        Raises ``ValueError`` if required config (SMTP credentials, recipient)
        is missing.
        """
        if self._running:
            return
        self._cfg.validate()
        self._running = True
        self._rotate()

    def stop(self) -> None:
        """Cancel the pending timer and stop."""
        self._running = False
        if self._timer is not None:
            self._timer.cancel()
            self._timer = None

    def __enter__(self) -> ScheduledEmailService:
        self.start()
        return self

    def __exit__(self, *exc: object) -> None:
        self.stop()
