from http import HTTPStatus

from flask import request
from flask_jwt_extended import jwt_required, get_jwt_identity

from app.extensions.utils.oauth_helper import OAuthBase
from app.http.requests.v1.auth_request import LogoutRequest, GetVerificationRequest
from app.http.responses import failure_response
from app.http.responses.presenters.v1.auth_presenter import (
    AuthenticationPresenter,
    LogoutPresenter,
    VerificationJWTPresenter,
)

from app.http.view import api
from app.http.view.authentication import auth_required
from core.domains.authentication.use_case.v1.auth_use_case import (
    AuthenticationUseCase,
    LogoutUseCase,
    VerificationJWTUseCase,
)
from core.exceptions import InvalidRequestException, NotFoundException
from core.use_case_output import UseCaseFailureOutput, FailureType


@api.route("/auth/v1/", methods=["GET"])
@jwt_required
@auth_required
def auth_for_testing_view():
    """
    인증 테스트 뷰
    """
    return AuthenticationPresenter().transform(AuthenticationUseCase().execute())


@api.route("/v1/auth/logout", methods=["POST"])
@jwt_required
@auth_required
def logout_view():
    """
        user logout from client
    """
    auth_header = request.headers.get("Authorization")
    bearer, _, token = auth_header.partition(" ")

    user_id = get_jwt_identity()

    try:
        dto = LogoutRequest(
            access_token=token, user_id=user_id
        ).validate_request_and_make_dto()
    except InvalidRequestException:
        return failure_response(
            UseCaseFailureOutput(
                message=FailureType.INVALID_REQUEST_ERROR,
                type=f"Invalid token input from header",
            )
        )

    return LogoutPresenter().transform(LogoutUseCase().execute(dto=dto))


@api.route("/v1/auth/verification", methods=["GET"])
def verification_view():
    """
        Verification from Client
        - 만료된 Access 토큰이 요청오면 무조건 갱신 처리
        - UUID와 user_id 맵핑으로 확인
        - UUID : UUID_v4
    """
    auth_header = request.headers.get("Authorization")
    uuid_v4 = request.args.get("uuid")

    try:
        oauth_base = OAuthBase(auth_header)
    except NotFoundException as e:
        return failure_response(
            UseCaseFailureOutput(
                type=f"{e.type_.get('msg')}",
                message=FailureType.NOT_FOUND_ERROR,
                code=HTTPStatus.NOT_FOUND,
            )
        )
    except InvalidRequestException as e:
        return failure_response(
            UseCaseFailureOutput(
                type=f"{e.message}",
                message=FailureType.INVALID_REQUEST_ERROR,
                code=HTTPStatus.BAD_REQUEST,
            )
        )

    token_to_bytes = oauth_base.access_token.encode("utf-8")

    # 토큰 자체에 대한 유효성 검증
    try:
        dto = GetVerificationRequest(
            token=token_to_bytes, uuid=uuid_v4
        ).validate_request_and_make_dto()
    except InvalidRequestException as e:
        return failure_response(
            UseCaseFailureOutput(
                type=f"{e.message}",
                message=FailureType.INVALID_REQUEST_ERROR,
                code=HTTPStatus.BAD_REQUEST,
            )
        )
    return VerificationJWTPresenter().transform(
        VerificationJWTUseCase().execute(dto=dto)
    )
