from __future__ import annotations

from dataclasses import dataclass
from typing import Callable, Generic, TypeVar

from .terminal_ui import SelectionOption, select_option


T = TypeVar("T")


@dataclass(slots=True)
class InteractiveSelectionResult(Generic[T]):
    status: str
    value: T | None = None
    message: str | None = None


def cancelled_result(message: str = "已取消") -> dict[str, str]:
    return {"status": "cancelled", "message": message}


def resolve_interactive_selection(
    args: object,
    *,
    title: str,
    unavailable_message: str,
    empty_message: str,
    load_options: Callable[[], list[SelectionOption[T]]],
) -> InteractiveSelectionResult[T]:
    input_stream = getattr(args, "_stdin", None)
    output_stream = getattr(args, "_stderr_stream", None)
    if input_stream is None or output_stream is None:
        return InteractiveSelectionResult(status="unavailable", message=unavailable_message)
    if not bool(getattr(input_stream, "isatty", lambda: False)()):
        return InteractiveSelectionResult(status="unavailable", message=unavailable_message)

    options = list(load_options())
    if not options:
        return InteractiveSelectionResult(status="empty", message=empty_message)

    value = select_option(
        title=title,
        options=options,
        input_stream=input_stream,
        output_stream=output_stream,
    )
    if value is None:
        return InteractiveSelectionResult(status="cancelled", message="已取消")
    return InteractiveSelectionResult(status="selected", value=value)


def resolve_interactive_text_input(
    args: object,
    *,
    prompt: str,
    unavailable_message: str,
) -> InteractiveSelectionResult[str]:
    input_stream = getattr(args, "_stdin", None)
    output_stream = getattr(args, "_stderr_stream", None)
    if input_stream is None or output_stream is None:
        return InteractiveSelectionResult(status="unavailable", message=unavailable_message)
    if not bool(getattr(input_stream, "isatty", lambda: False)()):
        return InteractiveSelectionResult(status="unavailable", message=unavailable_message)

    output_stream.write(prompt)
    output_stream.flush()
    line = input_stream.readline()
    text = str(line or "").strip()
    if not text:
        return InteractiveSelectionResult(status="cancelled", message="已取消")
    return InteractiveSelectionResult(status="selected", value=text)
