from datetime import date

from yera.events import (
    request_input_buttons,
    request_input_date_picker,
    request_input_slider,
    request_input_text,
)
from yera.events.blocks.base.layout import _current_layout
from yera.events.stream import await_input
from yera.models.llm_context import llm_context
from yera.models.llm_interfaces.base import TBaseModel
from yera.opaque import opaque


@opaque
def sys_prompt(prompt: str):
    llm = llm_context()
    llm.add_sys_line(prompt)


@opaque
def chat(prompt: str, **kwargs) -> str:
    llm = llm_context()
    return llm.prompt_chat(prompt, **kwargs)


@opaque
def struct(prompt: str, cls: type[TBaseModel], **kwargs) -> TBaseModel:
    llm = llm_context()
    return llm.prompt_struct(prompt, cls, **kwargs)


@opaque
def text_input(message: str | None = None) -> str:
    layout_ctx = _current_layout.get()
    if layout_ctx is not None:
        request_input_text(message)
        layout_ctx.input_count += 1
        layout_ctx.result_parsers.append(lambda x: x)
        return ""
    request_input_text(message)
    input_event = await_input()
    return input_event.data


@opaque
def buttons(options: list[str], label: str | None = None) -> str:
    layout_ctx = _current_layout.get()
    if layout_ctx is not None:
        request_input_buttons(options, label)
        layout_ctx.input_count += 1
        layout_ctx.result_parsers.append(lambda x: x)
        return ""
    request_input_buttons(options, label)
    input_event = await_input()
    return input_event.data


@opaque
def date_picker(
    label: str,
    default_date: date | str | None = None,
) -> date:
    layout_ctx = _current_layout.get()
    if layout_ctx is not None:
        request_input_date_picker(label, default_date)
        layout_ctx.input_count += 1
        layout_ctx.result_parsers.append(lambda x: date.fromisoformat(x))
        return date.today()
    request_input_date_picker(label, default_date)
    input_event = await_input()
    # Parse the string date from the input event
    date_str = input_event.data
    return date.fromisoformat(date_str)


@opaque
def slider(
    min_value: float,
    max_value: float,
    label: str,
    default_value: float | None = None,
) -> float:
    layout_ctx = _current_layout.get()
    if layout_ctx is not None:
        request_input_slider(min_value, max_value, label, default_value)
        layout_ctx.input_count += 1
        layout_ctx.result_parsers.append(lambda x: float(x))
        return 0.0
    request_input_slider(min_value, max_value, label, default_value)
    input_event = await_input()
    # Parse the float from the input event
    return float(input_event.data)
