from dataclasses import dataclass
from typing import Callable

from analyst_klondike.features.data_context.data_state import PythonTaskState
from analyst_klondike.features.teacher.create_screen.screen import push_create_edit_screen
from analyst_klondike.state.app_state import AppState, get_state
from analyst_klondike.state.base_action import BaseAction


@dataclass
class CreateTaskAction(BaseAction):
    type = "CREATE_TASK_ACTION"
    task_name: str


def apply(state: AppState, action: BaseAction) -> AppState:
    if isinstance(action, CreateTaskAction):
        existed_task_titles = [t.title for t in state.data.tasks.values()]

        if action.task_name in existed_task_titles:
            raise KeyError(
                f"Task with id = {action.task_name} " +
                "already exists: {", ".join(existed_task_titles)}"
            )
        if state.current.quiz_id is None:
            raise ValueError("No current quiz")

        new_task_id = _get_new_task_id(state.data.tasks)

        new_quiz = PythonTaskState(
            id=new_task_id,
            title=action.task_name,
            description="",
            quiz_id=state.current.quiz_id,
            code="",
            code_template=""
        )
        state.data.tasks[new_task_id] = new_quiz
        return state
    return state


def _get_new_task_id(tasks: dict[int, PythonTaskState]) -> int:
    delta = 0
    new_id = len(tasks) + 1
    while new_id in tasks:
        new_id += delta
    return new_id


def push_screen(dismiss_callback: Callable[[str | None], None]):
    def _is_title_unique(value: str) -> bool:
        state = get_state()
        return value not in state.data.quizes
    push_create_edit_screen(
        dismiss_callback,
        "Создать задачу",
        _is_title_unique
    )


__all__ = [
    "CreateTaskAction",
    "apply",
    "push_screen"
]
