import httpx
import uvicorn
from litestar import Litestar, get
from litestar.contrib.jinja import JinjaTemplateEngine
from litestar.di import Provide
from litestar.exceptions import HTTPException
from litestar.static_files import StaticFilesConfig
from litestar.template import TemplateConfig

from apps.httpapi.litestar.dependencies import (
    authenticate,
    get_authenticate_action,
    get_authenticator,
    get_bot_manager,
    get_chatbot_repo,
    get_create_chatbot_svc,
    get_create_or_update_chatbot_action,
    get_create_user_svc,
    get_get_chatbot_by_user_id_action,
    get_get_chatbot_by_user_id_svc,
    get_get_tokens_by_auth_code_svc,
    get_get_user_by_jwt_action,
    get_get_user_by_username_svc,
    get_is_valid_token_svc,
    get_refresh_token_svc,
    get_sentences_storer_svc,
    get_settings,
    get_update_chatbot_svc,
    get_update_user_svc,
    get_user_repo,
)
from apps.httpapi.litestar.errors import (
    after_exception_handler,
    http_exception_handler,
    httpx_status_error_handler,
)
from apps.httpapi.litestar.routes.api import (
    get_bot_settings,
    get_bot_status,
    get_index,
    get_tts_overlay,
    get_tts_permalink,
    manage_bot,
    save_bot_settings,
)
from apps.httpapi.litestar.routes.auth import get_code, login
from huesoporro.settings import Settings


@get("/healthz")
async def get_health() -> dict:
    return {"status": "ok"}


def create_app():
    return Litestar(
        route_handlers=[
            get_health,
            login,
            get_index,
            get_tts_overlay,
            get_tts_permalink,
            get_code,
            manage_bot,
            get_bot_status,
            save_bot_settings,
            get_bot_settings,
        ],
        static_files_config=(
            StaticFilesConfig(
                path="/tts_files",
                directories=[Settings.get().tts_cache_path],
            ),
            StaticFilesConfig(
                path="static",
                directories=[Settings.get().static_files_path],
            ),
        ),
        template_config=TemplateConfig(
            directory=Settings.get().templates_files_path,
            engine=JinjaTemplateEngine,
        ),
        exception_handlers={
            HTTPException: http_exception_handler,
            httpx.HTTPStatusError: httpx_status_error_handler,
        },
        after_exception=[after_exception_handler],
        dependencies={
            "s": Provide(get_settings, use_cache=True),
            "a": Provide(get_authenticator, use_cache=True),
            "user": Provide(authenticate),
            "bm": Provide(get_bot_manager, use_cache=True),
            "sss": Provide(get_sentences_storer_svc),
            "twitch_authenticator": Provide(get_authenticator),
            "authenticate_action": Provide(get_authenticate_action),
            "user_repo": Provide(get_user_repo),
            "chatbot_repo": Provide(get_chatbot_repo),
            "create_user_svc": Provide(get_create_user_svc),
            "update_chatbot_svc": Provide(get_update_chatbot_svc),
            "update_user_svc": Provide(get_update_user_svc),
            "create_chatbot_svc": Provide(get_create_chatbot_svc),
            "refresh_token_svc": Provide(get_refresh_token_svc),
            "is_valid_token_svc": Provide(get_is_valid_token_svc),
            "get_user_by_username_svc": Provide(get_get_user_by_username_svc),
            "get_chatbot_by_user_id_svc": Provide(get_get_chatbot_by_user_id_svc),
            "get_tokens_by_auth_code_svc": Provide(get_get_tokens_by_auth_code_svc),
            "get_user_by_jwt_action": Provide(get_get_user_by_jwt_action),
            "get_chatbot_by_user_id_action": Provide(get_get_chatbot_by_user_id_action),
            "create_or_update_chatbot_action": Provide(
                get_create_or_update_chatbot_action
            ),
        },
    )


app = create_app()

if __name__ == "__main__":
    s = Settings.get()
    config = uvicorn.Config("main:app", host=s.host, port=s.port, log_level="info")
    server = uvicorn.Server(config)
    server.run()
