"""SP37 Task 4: typed result for submit_file.

The CLI and HTTP layer both consume SubmitResult; keeping it in one
place means both surfaces agree on the response shape.
"""
from __future__ import annotations

from dataclasses import dataclass
from enum import Enum


class SubmitOutcome(str, Enum):
    """Outcome of a single submit_file invocation.

    Audit-event invariant: ``SUBMITTED`` emits a ``clearhouse.submitted``
    audit event; ``SKIPPED`` does NOT (re-running on an already-uploaded
    file must not flood the audit log with duplicate events). All
    failure outcomes (``PARSE_FAILED``, ``PAYER_MISMATCH``, ``DB_FAILED``,
    ``SFTP_FAILED``, ``UNEXPECTED_ERROR``) emit no event either —
    failures should be observable via the helper's return value, not
    the audit log.

    ``UNEXPECTED_ERROR`` is reserved for uncaught exceptions in the
    helper's own code (e.g. a bug in ``cycl_store.add``) — distinct
    from the typed ``SFTP_FAILED`` which means the SFTP layer itself
    raised. Operators reading ``outcome="unexpected_error"`` know to
    look at the bug tracker, not the SFTP server.
    """
    SUBMITTED = "submitted"
    SKIPPED = "skipped"
    PARSE_FAILED = "parse_failed"
    PAYER_MISMATCH = "payer_mismatch"
    DB_FAILED = "db_failed"
    SFTP_FAILED = "sftp_failed"
    UNEXPECTED_ERROR = "unexpected_error"


@dataclass(frozen=True)
class SubmitResult:
    """Return value of ``submit_file``: filename, outcome, and optional
    ``batch_id`` (populated when the DB write succeeded) and ``error``
    (populated on any failure outcome; ``None`` on ``SUBMITTED`` /
    ``SKIPPED``).
    """
    file: str
    outcome: SubmitOutcome
    batch_id: str | None = None
    error: str | None = None
