"""Delivery pipeline: save → commit → email → push."""

from __future__ import annotations

import tempfile
from pathlib import Path

from loguru import logger

from message_delivery.email import EmailSender
from message_delivery.errors import DeliveryError
from message_delivery.git import GitOperations
from message_delivery.models import DeliveryOptions, DeliveryResult
from message_delivery.saver import NoteSaver
from session_store import SessionMessage


class DeliveryPipeline:
    """Orchestrate the save → commit → email → push pipeline."""

    def __init__(
        self,
        saver: NoteSaver | None = None,
        git: GitOperations | None = None,
        emailer: EmailSender | None = None,
    ) -> None:
        self._saver = saver or NoteSaver()
        self._git = git or GitOperations()
        self._emailer = emailer or EmailSender()

    def deliver(
        self,
        message: SessionMessage,
        session_title: str,
        options: DeliveryOptions,
    ) -> DeliveryResult:
        """Run the delivery pipeline for *message*.

        1. Save the message as a markdown note (always).
        2. Commit the note (unless ``no_commit`` or ``dry_run``).
        3. Email the note (unless ``no_email`` or ``dry_run``).
        4. Push to the remote (unless ``no_push`` or ``dry_run``).

        In ``dry_run`` mode the note is saved to a temporary directory and
        commit/email/push are skipped.
        """
        committed = False
        emailed = False
        pushed = False

        # 1. Save (always).  In dry_run mode, save to a temp directory.
        if options.dry_run:
            tmp_dir = Path(tempfile.mkdtemp(prefix="message-delivery-dry-run-"))
            note_path = self._saver.save(message, session_title, tmp_dir, filename=options.filename)
            logger.info("Dry run: note saved to {} (commit/email/push skipped)", note_path)
            return DeliveryResult(
                note_path=note_path,
                committed=False,
                emailed=False,
                pushed=False,
            )

        project_root = self._git.find_project_root()
        note_path = self._saver.save(
            message, session_title, project_root, filename=options.filename
        )

        # 2. Commit
        if not options.no_commit:
            try:
                committed = self._git.commit(
                    note_path,
                    options.subject or f"Add note: {note_path.name}",
                )
            except DeliveryError:
                raise

        # 3. Email
        if not options.no_email:
            subject = options.subject or session_title
            try:
                self._emailer.send(note_path, subject, to=options.to_email)
                emailed = True
            except DeliveryError:
                raise

        # 4. Push
        if not options.no_push:
            try:
                self._git.push()
                pushed = True
            except DeliveryError:
                raise

        return DeliveryResult(
            note_path=note_path,
            committed=committed,
            emailed=emailed,
            pushed=pushed,
        )
