from __future__ import annotations

from dataclasses import fields, is_dataclass
from enum import Enum
from typing import Any

from flow_xhs.cli.spec.model import CliSpec, CommandSpec, DocTopicSpec
from flow_xhs.cli.spec.views import GroupView, get_group_view, list_root_entries


def export_cli_spec(spec: CliSpec) -> dict[str, Any]:
    return _to_jsonable(spec)


def export_command_spec(command: CommandSpec) -> dict[str, Any]:
    payload = _to_jsonable(command)
    parameters = payload.get("parameters", [])
    if isinstance(parameters, list):
        for param in parameters:
            requiredness = param.get("requiredness", {})
            mode = requiredness.get("mode")
            param["requiredness_mode"] = mode
            param["is_required"] = mode == "required"
            param["is_conditional"] = mode == "conditional"
            param["required_if"] = requiredness.get("message")
    payload["input_precedence"] = ["cli", "input_json", "default"]
    payload["supported_output_formats"] = ["json", "jsonl", "table"]
    return payload


def export_root_help(spec: CliSpec) -> dict[str, Any]:
    visible_global_options = tuple(param for param in spec.global_options if param.id not in {"help", "version"})
    return {
        "kind": "root",
        "cli_name": spec.cli_name,
        "summary": spec.summary,
        "description": spec.description,
        "canonical_syntax": spec.canonical_syntax,
        "commands": _to_jsonable(list_root_entries(spec)),
        "global_options": _to_jsonable(visible_global_options),
        "quick_start": _to_jsonable(tuple(spec.metadata.get("quick_start", ()))),
        "topics": _to_jsonable(spec.topics),
    }


def export_group_help(spec: CliSpec, path: tuple[str, ...]) -> dict[str, Any] | None:
    group = get_group_view(spec, path)
    if group is None:
        return None
    return _to_jsonable(group)


def export_group_view(group: GroupView) -> dict[str, Any]:
    return _to_jsonable(group)


def export_topic_help(topic: DocTopicSpec) -> dict[str, Any]:
    payload = _to_jsonable(topic)
    payload["kind"] = "topic"
    return payload


def _to_jsonable(value: Any) -> Any:
    if isinstance(value, Enum):
        return value.value
    if is_dataclass(value):
        return {field.name: _to_jsonable(getattr(value, field.name)) for field in fields(value)}
    if isinstance(value, tuple):
        return [_to_jsonable(item) for item in value]
    if isinstance(value, list):
        return [_to_jsonable(item) for item in value]
    if isinstance(value, dict):
        return {key: _to_jsonable(item) for key, item in value.items()}
    return value
