from pydantic import BaseModel, StrictStr, validator, ValidationError, UUID4

from app.extensions.utils.log_helper import logger_
from core.domains.oauth.dto.oauth_dto import GetOAuthLoginDto, GetOAuthAdminLoginDto
from core.domains.oauth.enum.oauth_enum import ProviderEnum
from core.exceptions import InvalidRequestException

logger = logger_.getLogger(__name__)


class GetProviderIdSchema(BaseModel):
    provider_id: StrictStr = None
    provider: StrictStr
    uuid: UUID4

    @validator("provider_id")
    def provider_id_match(cls, provider_id):
        if not provider_id or provider_id == "None":
            raise ValidationError("no provider id")
        return provider_id

    @validator("provider")
    def provider_match(cls, provider):
        provider_list = tuple([provider.value for provider in list(ProviderEnum)])
        if provider is None or provider.lower() not in provider_list:
            raise ValidationError("value must be equal to provider name")
        return provider

    @validator("uuid")
    def uuid_validation(cls, uuid):
        return str(uuid)


class GetOAuthLoginRequest:
    def __init__(self, provider_id: str, provider: str, uuid: str):
        self.provider_id = provider_id
        self.provider = provider
        self.uuid = uuid

    def validate_request_and_make_dto(self) -> GetOAuthLoginDto:
        try:
            schema = GetProviderIdSchema(
                provider_id=self.provider_id, provider=self.provider, uuid=self.uuid
            ).dict()
            return GetOAuthLoginDto(**schema)
        except ValidationError as e:
            logger.error(
                f"[GetOAuthLoginRequest][validate_request_and_make_dto] error : {e}"
            )
            raise InvalidRequestException(message=e.errors())


class GetAdminProviderIdSchema(BaseModel):
    provider_id: StrictStr = None
    provider: StrictStr

    @validator("provider_id")
    def provider_id_match(cls, provider_id):
        if not provider_id or provider_id == "None":
            raise ValidationError("no provider id")
        return provider_id

    @validator("provider")
    def provider_match(cls, provider):
        provider_list = tuple([provider.value for provider in list(ProviderEnum)])
        if provider is None or provider.lower() not in provider_list:
            raise ValidationError("value must be equal to provider name")
        return provider


class GetOAuthAdminLoginRequest:
    def __init__(self, provider_id: str, provider: str):
        self.provider_id = provider_id
        self.provider = provider

    def validate_request_and_make_dto(self) -> GetOAuthAdminLoginDto:
        try:
            schema = GetAdminProviderIdSchema(
                provider_id=self.provider_id, provider=self.provider
            ).dict()
            return GetOAuthAdminLoginDto(**schema)
        except ValidationError as e:
            logger.error(
                f"[GetOAuthAdminLoginRequest][validate_request_and_make_dto] error : {e}"
            )
            raise InvalidRequestException(message=e.errors())
