from __future__ import annotations

from flow_xhs.cli.spec.enums import (
    CommandStatus,
    InputSourceKind,
    ParameterGroup,
    ParameterKind,
    ParameterScope,
    RequirednessMode,
    ValueKind,
)
from flow_xhs.cli.spec.model import (
    AllowedValueSpec,
    CommandHelpSpec,
    CommandSpec,
    ConstraintSpec,
    DefaultSpec,
    InputSourceBinding,
    OutputSpec,
    ParameterSpec,
    RequirednessSpec,
    ValueTypeSpec,
)


def build_global_option(
    *,
    id: str,
    cli_name: str,
    summary: str,
    description: str | None = None,
    kind: ParameterKind = ParameterKind.OPTION,
    value_kind: ValueKind = ValueKind.STRING,
    default: DefaultSpec | None = None,
    allowed_values: tuple[AllowedValueSpec, ...] = (),
) -> ParameterSpec:
    return ParameterSpec(
        id=id,
        name=id,
        cli_names=(cli_name,),
        scope=ParameterScope.GLOBAL,
        kind=kind,
        group=ParameterGroup.OUTPUT_CONTROLS,
        summary=summary,
        description=description,
        value_type=ValueTypeSpec(kind=value_kind, nullable=kind == ParameterKind.FLAG),
        requiredness=RequirednessSpec(mode=RequirednessMode.OPTIONAL),
        default=default,
        allowed_values=allowed_values,
    )


def build_command(
    *,
    id: str,
    path: tuple[str, ...],
    summary: str,
    description: str | None = None,
    success_command: str,
    success_schema_ref: str = "xhs/schemas/command-output-success.json",
    error_schema_ref: str = "xhs/schemas/command-output-error.json",
    parameters: tuple[ParameterSpec, ...] = (),
    constraints: tuple[ConstraintSpec, ...] = (),
    examples: tuple = (),
    related_commands: tuple[str, ...] = (),
    output: OutputSpec | None = None,
    help: CommandHelpSpec | None = None,
) -> CommandSpec:
    return CommandSpec(
        id=id,
        path=path,
        display_path="flow-xhs " + " ".join(path),
        summary=summary,
        description=description,
        status=CommandStatus.STABLE,
        parameters=parameters,
        constraints=constraints,
        examples=examples,
        output=output
        or OutputSpec(
            success_command=success_command,
            success_schema_ref=success_schema_ref,
            error_schema_ref=error_schema_ref,
            data_shape_summary="命令结果对象",
        ),
        related_commands=related_commands,
        help=help,
    )

def build_command_option(
    *,
    id: str,
    cli_name: str,
    group: ParameterGroup,
    summary: str,
    description: str | None = None,
    value_kind: ValueKind = ValueKind.STRING,
    min_value: int | float | None = None,
    max_value: int | float | None = None,
    required: bool = False,
    default: DefaultSpec | None = None,
    allowed_values: tuple[AllowedValueSpec, ...] = (),
    nullable: bool = True,
) -> ParameterSpec:
    return ParameterSpec(
        id=id,
        name=id,
        cli_names=(cli_name,),
        scope=ParameterScope.COMMAND,
        kind=ParameterKind.OPTION,
        group=group,
        summary=summary,
        description=description,
        value_type=ValueTypeSpec(kind=value_kind, min=min_value, max=max_value, nullable=nullable),
        requiredness=RequirednessSpec(
            mode=RequirednessMode.REQUIRED if required else RequirednessMode.OPTIONAL,
        ),
        default=default,
        allowed_values=allowed_values,
    )


def build_input_source_option(*, summary: str, fields: str, description: str | None = None) -> ParameterSpec:
    return ParameterSpec(
        id="input",
        name="input",
        cli_names=("--input",),
        scope=ParameterScope.COMMAND,
        kind=ParameterKind.INPUT_SOURCE,
        group=ParameterGroup.INPUT_SOURCES,
        summary=summary,
        description=description,
        value_type=ValueTypeSpec(kind=ValueKind.STRING, format="json-file-or-stdin", nullable=True),
        requiredness=RequirednessSpec(mode=RequirednessMode.OPTIONAL),
        input_bindings=(
            InputSourceBinding(
                source=InputSourceKind.INPUT_JSON,
                priority=2,
                field_name=fields,
                note="CLI > --input > default",
            ),
        ),
    )
