"""Gitlab SSO Oauth Helper class."""

from typing import TYPE_CHECKING, ClassVar, List, Optional, Tuple, Union
from urllib.parse import urljoin

import pydantic

from .base import DiscoveryDocument, OpenID, SSOBase
from .constant import ProviderEnum

if TYPE_CHECKING:
    import httpx  # pragma: no cover


class GitlabSSO(SSOBase):
    """Class providing login via Gitlab SSO."""

    provider = ProviderEnum.GITLAB
    scope: ClassVar = ['read_user', 'openid', 'profile']
    additional_headers: ClassVar = {'accept': 'application/json'}
    base_endpoint_url = 'https://gitlab.com'

    def __init__(
        self,
        client_id: str,
        client_secret: str,
        redirect_uri: Optional[Union[pydantic.AnyHttpUrl, str]] = None,
        allow_insecure_http: bool = False,
        use_state: bool = False,  # TODO: Remove use_state argument
        scope: Optional[List[str]] = None,
        base_endpoint_url: Optional[str] = None,
    ) -> None:
        super().__init__(
            client_id,
            client_secret,
            redirect_uri,
            allow_insecure_http,
            use_state,  # TODO: Remove use_state argument
            scope,
        )
        self.base_endpoint_url = base_endpoint_url or self.base_endpoint_url

    async def get_discovery_document(self) -> DiscoveryDocument:
        """Override the discovery document method to return Yandex OAuth endpoints."""
        return {
            'authorization_endpoint': urljoin(self.base_endpoint_url, '/oauth/authorize'),
            'token_endpoint': urljoin(self.base_endpoint_url, '/oauth/token'),
            'userinfo_endpoint': urljoin(self.base_endpoint_url, '/api/v4/user'),
        }

    def _parse_name(self, full_name: Optional[str]) -> Tuple[Union[str, None], Union[str, None]]:
        """Parses the full name from Gitlab into the first and last name."""
        if not full_name or not isinstance(full_name, str):
            return None, None

        name_parts = full_name.split()

        if len(name_parts) == 1:
            return name_parts[0], None

        first_name = name_parts[0]
        last_name = ' '.join(name_parts[1:])
        return first_name, last_name

    async def openid_from_response(self, response: dict, session: Optional['httpx.AsyncClient'] = None) -> OpenID:
        """Converts Gitlab user info response to OpenID object."""
        first_name, last_name = self._parse_name(response.get('name'))

        return OpenID(
            email=response['email'],
            provider=self.provider,
            id=str(response['id']),
            first_name=first_name,
            last_name=last_name,
            display_name=response['username'],
            picture=response['avatar_url'],
        )
