from typing import Callable, Optional, Type, cast

from fastapi import APIRouter, HTTPException, Request, status

from app.models import users
from app.common.user import ErrorCode, run_handler
from app.users.user import (
    CreateUserProtocol,
    InvalidPasswordException,
    UserAlreadyExists,
    ValidatePasswordProtocol,
)


def get_register_router(
    create_user: CreateUserProtocol,
    user_model: Type[users.BaseUser],
    user_create_model: Type[users.BaseUserCreate],
    after_register: Optional[Callable[[users.UD, Request], None]] = None,
    validate_password: Optional[ValidatePasswordProtocol] = None,
) -> APIRouter:
    """Generate a router with the register route."""
    router = APIRouter()

    @router.post(
        "/register", response_model=user_model, status_code=status.HTTP_201_CREATED
    )
    async def register(request: Request, user: user_create_model):  # type: ignore
        user = cast(users.BaseUserCreate, user)  # Prevent mypy complain
        if validate_password:
            try:
                await validate_password(user.password, user)
            except InvalidPasswordException as e:
                raise HTTPException(
                    status_code=status.HTTP_400_BAD_REQUEST,
                    detail={
                        "code": ErrorCode.REGISTER_INVALID_PASSWORD,
                        "reason": e.reason,
                    },
                )

        try:
            created_user = await create_user(user, safe=True)
        except UserAlreadyExists:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=ErrorCode.REGISTER_USER_ALREADY_EXISTS,
            )

        if after_register:
            await run_handler(after_register, created_user, request)

        return created_user

    return router

[((23, 13, 23, 24), 'fastapi.APIRouter', 'APIRouter', ({}, {}), '()', False, 'from fastapi import APIRouter, HTTPException, Request, status\n'), ((29, 15, 29, 47), 'typing.cast', 'cast', ({(29, 20, 29, 40): 'users.BaseUserCreate', (29, 42, 29, 46): 'user'}, {}), '(users.BaseUserCreate, user)', False, 'from typing import Callable, Optional, Type, cast\n'), ((45, 18, 48, 13), 'fastapi.HTTPException', 'HTTPException', (), '', False, 'from fastapi import APIRouter, HTTPException, Request, status\n'), ((51, 18, 51, 68), 'app.common.user.run_handler', 'run_handler', ({(51, 30, 51, 44): 'after_register', (51, 46, 51, 58): 'created_user', (51, 60, 51, 67): 'request'}, {}), '(after_register, created_user, request)', False, 'from app.common.user import ErrorCode, run_handler\n'), ((34, 22, 40, 17), 'fastapi.HTTPException', 'HTTPException', (), '', False, 'from fastapi import APIRouter, HTTPException, Request, status\n')]