from litestar import Request
from litestar.exceptions import HTTPException

from huesoporro.actions.chatbot.create_or_update_chatbot import (
    CreateOrUpdateChatbotAction,
)
from huesoporro.actions.chatbot.get_chatbot_by_user_id import GetChatbotByUserIdAction
from huesoporro.actions.users.authenticate_user import AuthenticateUserAction
from huesoporro.actions.users.get_user_by_jwt import GetUserByJWTAction
from huesoporro.bot import BotsManager
from huesoporro.infra.authenticator import TwitchAuthenticator
from huesoporro.infra.repos import ChatbotRepo, UserRepo
from huesoporro.libs.db import MarkovDatabase
from huesoporro.models import Chatbot, User
from huesoporro.settings import Settings
from huesoporro.svc.chatbot_svcs import (
    CreateChatbotSvc,
    GetChatbotByUserIdSvc,
    UpdateChatbotSvc,
)
from huesoporro.svc.store import SentenceStorerSvc
from huesoporro.svc.users_svcs import (
    CreateUserSvc,
    GetTwitchAuthByAuthCodeSvc,
    GetUserByUsernameSvc,
    IsValidTokenSvc,
    RefreshTokenSvc,
    UpdateUserSvc,
)


async def get_settings() -> Settings:
    return Settings.get()


async def get_authenticator(s: Settings) -> TwitchAuthenticator:
    return TwitchAuthenticator(s=s)


async def get_chatbot_repo(s: Settings):
    return ChatbotRepo(s=s)


async def get_get_chatbot_by_user_id_svc(chatbot_repo: ChatbotRepo):
    return GetChatbotByUserIdSvc(repo=chatbot_repo)


async def get_get_tokens_by_auth_code_svc(
    twitch_authenticator: TwitchAuthenticator, s: Settings
):
    return GetTwitchAuthByAuthCodeSvc(s=s, authenticator=twitch_authenticator)


async def get_create_chatbot_svc(chatbot_repo: ChatbotRepo):
    return CreateChatbotSvc(repo=chatbot_repo)


async def get_user_repo(s: Settings):
    return UserRepo(s=s)


async def get_create_user_svc(user_repo: UserRepo):
    return CreateUserSvc(user_repo=user_repo)


async def get_update_user_svc(user_repo: UserRepo):
    return UpdateUserSvc(user_repo=user_repo)


async def get_refresh_token_svc(twitch_authenticator: TwitchAuthenticator):
    return RefreshTokenSvc(twitch_authenticator=twitch_authenticator)


async def get_is_valid_token_svc(twitch_authenticator: TwitchAuthenticator):
    return IsValidTokenSvc(authenticator=twitch_authenticator)


async def get_get_user_by_username_svc(user_repo: UserRepo):
    return GetUserByUsernameSvc(user_repo=user_repo)


async def get_get_user_by_jwt_action(
    get_user_by_username_svc: GetUserByUsernameSvc,
    update_user_svc: UpdateUserSvc,
    is_valid_token_svc: IsValidTokenSvc,
    refresh_token_svc: RefreshTokenSvc,
    s: Settings,
):
    return GetUserByJWTAction(
        get_user_by_username_svc=get_user_by_username_svc,
        update_user_svc=update_user_svc,
        refresh_token_svc=refresh_token_svc,
        is_valid_token_svc=is_valid_token_svc,
        s=s,
    )


async def authenticate(
    request: Request, get_user_by_jwt_action: GetUserByJWTAction
) -> User:
    token = request.query_params.get("huesoporro_token")
    if token:
        user = await get_user_by_jwt_action.run(token)
        if not user:
            raise HTTPException(detail="User does not exist", status_code=404)
        return user

    cookies = request.cookies.get("huesoporroAuth")
    if cookies:
        user = await get_user_by_jwt_action.run(cookies)
        if not user:
            raise HTTPException(detail="User does not exist", status_code=404)
        return user

    raise HTTPException(status_code=401, detail="Unauthorized")


async def get_sentences_storer_svc(db: MarkovDatabase):
    return SentenceStorerSvc(db=db)


async def get_update_chatbot_svc(chatbot_repo: ChatbotRepo):
    return UpdateChatbotSvc(repo=chatbot_repo)


async def get_create_or_update_chatbot_action(
    create_chatbot_svc: CreateChatbotSvc,
    update_chatbot_svc: UpdateChatbotSvc,
    get_chatbot_by_user_id_svc: GetChatbotByUserIdSvc,
):
    return CreateOrUpdateChatbotAction(
        create_chatbot_svc=create_chatbot_svc,
        update_chatbot_svc=update_chatbot_svc,
        get_chatbot_by_user_id_svc=get_chatbot_by_user_id_svc,
    )


async def get_get_chatbot_by_user_id_action(
    get_chatbot_by_user_id_svc: GetChatbotByUserIdSvc,
):
    return GetChatbotByUserIdAction(
        get_chatbot_by_user_id_svc=get_chatbot_by_user_id_svc
    )


async def get_authenticate_action(
    s: Settings,
    get_tokens_by_auth_code_svc: GetTwitchAuthByAuthCodeSvc,
    get_user_by_username_svc: GetUserByUsernameSvc,
    create_user_svc: CreateUserSvc,
    update_user_svc: UpdateUserSvc,
):
    return AuthenticateUserAction(
        s=s,
        get_tokens_by_auth_code_svc=get_tokens_by_auth_code_svc,
        get_user_by_username_svc=get_user_by_username_svc,
        create_user_svc=create_user_svc,
        update_user_svc=update_user_svc,
    )


async def get_bot_manager(s: Settings):
    return BotsManager(s=s)


async def chatbot(
    get_chatbot_by_user_id_action: GetChatbotByUserIdAction,
    create_or_update_chatbot_action: CreateOrUpdateChatbotAction,
    user: User,
) -> Chatbot:
    cb = await get_chatbot_by_user_id_action.run(user_id=user.id)
    if cb:
        return cb
    return await create_or_update_chatbot_action.run(
        user_id=user.id,
    )
