"""IdentityVerifier seam (§2.3). Ingress identity goes through ONE interface with pluggable adapters, so the
core stays stable while identity sources grow. v1 core: Ed25519 / ES256 + did:web. Stubs: Base / Google /
EUDI. The verified identity outcome binds to the AnchoredRoot MUST#3 assurance level (A3): an unsigned /
unverified VEB is the LOWEST level, explicitly — a relying party may never read a lower level as higher.
"""

from __future__ import annotations

import abc
import enum
from dataclasses import dataclass
from typing import Optional


class AssuranceLevel(enum.IntEnum):
    """A3 — ordered so a consumer can pin a minimum and reject anything below. Mirrors AnchoredRoot MUST#3.
    There is NO default; absence of a level is rejection (handled by the caller, fail-closed)."""

    UNSIGNED = 0          # no verified signer — the lowest level, never readable as authentic
    SIGNED = 1            # a verified signature from a known identity adapter
    SIGNATURE_AUTHENTIC = 2  # anchored + k-of-n real validator signatures (the NEO with-header path, #144)
    WITNESS_ATTESTED = 3  # an external witness re-verified and co-signed (Ledger phase)


@dataclass(frozen=True)
class VerifiedIdentity:
    subject_ref: str          # an authorized reference / DID — never raw personal data
    method: str               # e.g. "ed25519", "es256", "did:web"
    assurance: AssuranceLevel


class IdentityVerifier(abc.ABC):
    """One verifier surface; concrete adapters implement `verify`. The router/ingress depends on this, not on
    any concrete method."""

    @abc.abstractmethod
    def method(self) -> str:
        """The identity method this adapter handles (e.g. 'ed25519', 'did:web')."""

    @abc.abstractmethod
    def verify(self, signing_input: bytes, signature: bytes, key_ref: str) -> Optional[VerifiedIdentity]:
        """Return a `VerifiedIdentity` on success, or `None` on failure (fail-closed — the caller treats a
        missing/failed verification as `UNSIGNED`, never as a higher level)."""
