from dataclasses import dataclass, field
from typing import Any, Protocol


class VerificationProviderError(Exception):
    def __init__(self, message: str, *, status_code: int = 500, code: int | None = None, raw: Any = None):
        super().__init__(message)
        self.status_code = status_code
        self.message = message
        self.code = code
        self.raw = raw


@dataclass(frozen=True)
class VerificationResult:
    passed: bool
    mode: str
    provider: str
    status: str
    reason: str = ""
    score: float | None = None
    external_id: str | None = None
    raw: dict[str, Any] = field(default_factory=dict)


@dataclass(frozen=True)
class RedirectSession:
    url: str
    external_id: str | None = None
    expires_in: int | None = None
    raw: dict[str, Any] = field(default_factory=dict)


class VerificationProvider(Protocol):
    name: str
    supported_modes: tuple[str, ...]

    async def verify_two_factor(self, *, real_name: str, id_card_no: str) -> VerificationResult:
        """Verify real name + identity card number."""

    async def verify_three_factor(
        self,
        *,
        real_name: str,
        id_card_no: str,
        phone: str,
    ) -> VerificationResult:
        """Verify real name + identity card number + phone number."""

    async def verify_face_api(
        self,
        *,
        real_name: str,
        id_card_no: str,
        image_base64: str,
        image_type: str = "BASE64",
    ) -> VerificationResult:
        """Verify real name + identity card number + face image."""

    async def create_redirect_session(
        self,
        *,
        real_name: str,
        id_card_no: str,
        return_url: str,
        notify_url: str | None = None,
    ) -> RedirectSession:
        """Create a third-party redirect verification session."""

    async def get_redirect_result(
        self,
        *,
        external_id: str,
        real_name: str,
        id_card_no: str,
    ) -> VerificationResult:
        """Query a third-party redirect verification result."""
