from typing import Literal

from litestar import MediaType, Response, get, put
from litestar.datastructures import UploadFile
from litestar.response import Template
from pydantic import BaseModel, ConfigDict

from huesoporro.actions.chatbot.create_or_update_chatbot import (
    CreateOrUpdateChatbotAction,
)
from huesoporro.actions.chatbot.get_chatbot_by_user_id import GetChatbotByUserIdAction
from huesoporro.bot import BotsManager
from huesoporro.models import Chatbot, User


class ManageBotDTO(BaseModel):
    command: Literal["start", "stop"]
    channel_name: str | None = None


class ImportTextFileDTO(BaseModel):
    file: UploadFile
    channel_name: str

    model_config = ConfigDict(arbitrary_types_allowed=True)


class UpdateChatbotDTO(BaseModel):
    automatic_generation_timer: int = 300
    automatic_quote_timer: int = 500
    mods: list[str]


@get(
    "/tts",
    media_type=MediaType.HTML,
)
async def get_tts_overlay(user: User) -> Template:
    return Template(template_name="tts.html")


@get(
    "/tts/permalink",
    media_type=MediaType.HTML,
)
async def get_tts_permalink(access_token: str) -> Template:
    """Handler for the /tts permalink endpoint to be used by apps that can only give the authentication as a query
    param and not as a cookie, i.e. OBS"""

    return Template(
        template_name="tts.html",
    )


@get(
    "/",
    media_type=MediaType.HTML,
)
async def get_index(
    user: User, get_chatbot_by_user_id_action: GetChatbotByUserIdAction
) -> Template:
    chatbot_settings = await get_chatbot_by_user_id_action.run(user_id=user.id)
    return Template(
        template_name="index.html",
        context=chatbot_settings.model_dump() if chatbot_settings else {},
    )


@put("/api/v1/bot")
async def manage_bot(
    user: User,
    data: ManageBotDTO,
    create_or_update_chatbot_action: CreateOrUpdateChatbotAction,
    get_chatbot_by_user_id_action: GetChatbotByUserIdAction,
    bm: BotsManager,
) -> Response:
    chatbot = await get_chatbot_by_user_id_action.run(
        user_id=user.id
    ) or await create_or_update_chatbot_action.run(
        user_id=user.id,
    )

    if data.command == "start":
        if not data.channel_name:
            return Response({"message": "Channel name is required"}, status_code=400)
        bm.add_bot(user, data.channel_name, chatbot=chatbot)  # type: ignore[arg-type]
        if user.username in bm.bots:
            await bm.run_user_bot(user)
            return Response({"message": "Bot started"})
    if data.command == "stop" and user.username in bm.bots:
        await bm.stop_user_bot(user)
        return Response({"message": "Bot stopped"})
    return Response({"message": "Invalid command"}, status_code=400)


@get("/api/v1/bot")
async def get_bot_status(user: User, bm: BotsManager) -> dict:
    if user.username not in bm.bots:
        return {"status": "ko"}
    return {"status": "ok"}


@get("/api/v1/bot/settings")
async def get_bot_settings(chatbot: Chatbot) -> Chatbot:
    return chatbot


@put("/api/v1/bot/settings")
async def save_bot_settings(
    user: User,
    data: UpdateChatbotDTO,
    create_or_update_chatbot_action: CreateOrUpdateChatbotAction,
) -> dict:
    await create_or_update_chatbot_action.run(
        user_id=user.id,
        automatic_generation_timer=data.automatic_generation_timer,
        automatic_quote_timer=data.automatic_quote_timer,
        mods=data.mods,
    )
    return {"status": "ok"}
