from __future__ import annotations

from typing import Any

CANONICAL_TASK_STATUSES: tuple[str, ...] = (
    "wait",
    "todo",
    "progress",
    "done",
    "cancel",
)

TASK_STATUS_CODES: dict[str, str] = {
    "WAIT": "wait",
    "TODO": "todo",
    "PROG": "progress",
    "DONE": "done",
    "CNCL": "cancel",
}

LEGACY_TASK_STATUS_ALIASES: dict[str, str] = {
    "blocked": "wait",
    "waiting": "wait",
    "in_progress": "progress",
    "in-progress": "progress",
    "prog": "progress",
    "cancelled": "cancel",
    "canceled": "cancel",
    "cncl": "cancel",
}

OPEN_TASK_STATUSES: frozenset[str] = frozenset({"wait", "todo", "progress"})
ACTIVE_TASK_STATUSES: frozenset[str] = frozenset({"wait", "progress"})
TERMINAL_TASK_STATUSES: frozenset[str] = frozenset({"done", "cancel"})

TASK_STATUS_ORDER: dict[str, int] = {
    "todo": 0,
    "wait": 1,
    "progress": 1,
    "done": 2,
    "cancel": 2,
}

TASK_STATUS_LABELS: dict[str, str] = {
    "wait": "wait",
    "todo": "todo",
    "progress": "progress",
    "done": "done",
    "cancel": "cancel",
}


def raw_status_value(status: Any) -> str:
    if hasattr(status, "value"):
        status = status.value
    return str(status or "").strip()


def normalize_task_status(status: Any, *, default: str | None = None) -> str:
    """Normalize canon task statuses plus legacy aliases to stored values."""
    value = raw_status_value(status).lower()
    if not value:
        if default is not None:
            return default
        raise ValueError("task status is required")
    value = LEGACY_TASK_STATUS_ALIASES.get(value, value)
    if value not in CANONICAL_TASK_STATUSES:
        allowed = ", ".join(CANONICAL_TASK_STATUSES)
        aliases = ", ".join(sorted(LEGACY_TASK_STATUS_ALIASES))
        raise ValueError(f"task status must be one of {allowed}; legacy aliases: {aliases}")
    return value


def status_value(status: Any, *, default: str | None = None) -> str:
    """Compatibility wrapper used by lifecycle and reconciliation code."""
    return normalize_task_status(status, default=default)


def is_open_task_status(status: Any) -> bool:
    return normalize_task_status(status, default="todo") in OPEN_TASK_STATUSES


def is_terminal_task_status(status: Any) -> bool:
    return normalize_task_status(status, default="todo") in TERMINAL_TASK_STATUSES
