from abc import abstractmethod
from typing import Protocol

from template_project.application.common.data_structure import to_data_structure
from template_project.application.common.errors import ApplicationError, to_error


@to_data_structure
class OAuthTokenResponse:
    access_token: str
    expires_in: int | None = None


@to_data_structure
class OAuthUserInfo:
    user_id: str
    email: str | None = None
    display_name: str | None = None
    first_name: str | None = None
    last_name: str | None = None
    avatar_url: str | None = None
    phone: str | None = None


@to_error
class OAuthExchangeCodeError(ApplicationError):
    pass


@to_error
class OAuthLoadUserInfoError(ApplicationError):
    pass


class OAuthClient(Protocol):
    @abstractmethod
    async def exchange_code(self, code: str) -> OAuthTokenResponse:
        raise NotImplementedError

    @abstractmethod
    async def load_user_info(self, access_token: str) -> OAuthUserInfo:
        raise NotImplementedError
