from __future__ import annotations

from flow_xhs import __version__
from flow_xhs.cli.spec.builders import (
    build_command as _command,
    build_command_option as _command_option,
    build_global_option as _global_option,
    build_input_source_option as _input_source_option,
)
from flow_xhs.contracts.command_rules import (
    ACCOUNT_LOGIN_MODE_VALUES,
    ACCOUNT_LOGIN_TIMEOUT_DEFAULT,
    ACCOUNT_LOGIN_TIMEOUT_MIN,
    BOOLEAN_LITERAL_VALUES,
    NOTE_GET_COMMENT_SIZE_DEFAULT,
    NOTE_GET_COMMENT_SIZE_MIN,
    NOTE_GET_SUB_COMMENT_SIZE_DEFAULT,
    NOTE_GET_SUB_COMMENT_SIZE_MIN,
    NOTE_SEARCH_SIZE_DEFAULT,
    PUBLISH_TARGET_VALUES,
    USER_SEARCH_SIZE_MIN,
    NOTE_SEARCH_SIZE_MIN,
    USER_SEARCH_SIZE_DEFAULT,
)
from flow_xhs.platform.search_filters import (
    get_filter_aliases,
    get_filter_canonical_values,
    get_filter_label,
)
from flow_xhs.cli.spec.enums import (
    DefaultKind,
    ExampleCategory,
    InputSourceKind,
    ParameterGroup,
    ParameterKind,
    ParameterScope,
    RequirednessMode,
    ValueKind,
)
from flow_xhs.cli.spec.model import (
    CliSpec,
    CommandHelpSpec,
    ConditionExpr,
    DefaultSpec,
    ExampleSpec,
    EventSpec,
    EventTypeSpec,
    InputSourceBinding,
    ParameterSpec,
    RequirednessSpec,
    ValueTypeSpec,
    AllowedValueSpec,
    OutputSpec,
)
from flow_xhs.cli.spec.validate import validate_cli_spec


SUCCESS_SCHEMA = "xhs/schemas/command-output-success.json"
ERROR_SCHEMA = "xhs/schemas/command-output-error.json"


FORMAT_OPTION = _global_option(
    id="format",
    cli_name="--format",
    summary="输出格式。",
    description="自动化调用建议使用 json；jsonl 适合事件流处理；table 适合人工阅读。",
    value_kind=ValueKind.ENUM,
    default=DefaultSpec(kind=DefaultKind.STATIC, value="table", display_value="table"),
    allowed_values=(
        AllowedValueSpec("json"),
        AllowedValueSpec("jsonl"),
        AllowedValueSpec("table"),
    ),
)
OUT_OPTION = _global_option(
    id="out",
    cli_name="--out",
    summary="输出文件路径。",
    description="仅写入最终结构化结果，不包含过程日志与事件流。",
    value_kind=ValueKind.PATH,
)
QUIET_OPTION = _global_option(
    id="quiet",
    cli_name="--quiet",
    summary="静默日志，仅输出结果。",
    description="开启后仅保留结果输出，stderr 事件仍会按命令契约输出。",
    kind=ParameterKind.FLAG,
    value_kind=ValueKind.BOOLEAN,
    default=DefaultSpec(kind=DefaultKind.STATIC, value=False, display_value="false"),
)
TRACE_ID_OPTION = _global_option(
    id="trace_id",
    cli_name="--trace-id",
    summary="请求链路 ID。",
    description="建议每次调用传入唯一值，便于跨系统串联日志与错误排查。",
    default=DefaultSpec(kind=DefaultKind.DYNAMIC, display_value="auto-generated"),
)
HELP_OPTION = ParameterSpec(
    id="help",
    name="help",
    cli_names=("--help", "-h"),
    scope=ParameterScope.GLOBAL,
    kind=ParameterKind.FLAG,
    group=ParameterGroup.OUTPUT_CONTROLS,
    summary="显示帮助并退出。",
    description="可用于 root、group 或 command 层级；支持配合 `--format json` 输出机读帮助。",
    value_type=ValueTypeSpec(kind=ValueKind.BOOLEAN, nullable=True),
    requiredness=RequirednessSpec(mode=RequirednessMode.OPTIONAL),
)
VERSION_OPTION = _global_option(
    id="version",
    cli_name="--version",
    summary="显示版本并退出。",
    description="仅输出版本号，不执行命令逻辑。",
    kind=ParameterKind.FLAG,
    value_kind=ValueKind.BOOLEAN,
)
NOTE_PUBLISH_TARGET = _command_option(
    id="target",
    cli_name="--target",
    group=ParameterGroup.REQUIRED_INPUTS,
    summary="发布目标类型。",
    description="当前支持 image、video；自动化调用应显式传入，避免依赖输入推断。",
    value_kind=ValueKind.ENUM,
    required=True,
    allowed_values=tuple(AllowedValueSpec(value) for value in PUBLISH_TARGET_VALUES),
    nullable=False,
)

def _filter_allowed_values(field: str) -> tuple[AllowedValueSpec, ...]:
    return tuple(
        AllowedValueSpec(
            value=value,
            label=get_filter_label(field, value),
            aliases=get_filter_aliases(field, value),
        )
        for value in get_filter_canonical_values(field)
    )
FLOW_XHS_SPEC = CliSpec(
    spec_version="1.0",
    cli_version=__version__,
    cli_name="flow-xhs",
    product_name="Flow XHS CLI",
    summary="小红书账号、搜索与发布一站式命令行工具。",
    description="面向人工与 Agent 的统一 CLI 契约；通过 help 与 JSON 导出提供可执行语义。",
    canonical_syntax="flow-xhs [OPTIONS] <COMMAND>",
    global_options=(
        FORMAT_OPTION,
        OUT_OPTION,
        QUIET_OPTION,
        TRACE_ID_OPTION,
        HELP_OPTION,
        VERSION_OPTION,
    ),
    commands=(
        _command(
            id="init",
            path=("init",),
            summary="初始化运行时目录与本地存储。",
            success_command="init",
            output=OutputSpec(
                success_command="init",
                success_schema_ref=SUCCESS_SCHEMA,
                error_schema_ref=ERROR_SCHEMA,
                data_shape_summary="运行时目录与基础配置路径对象。",
            ),
            examples=(
                ExampleSpec(
                    id="init_minimal",
                    title="初始化运行时",
                    category=ExampleCategory.MINIMAL,
                    command="flow-xhs init",
                    machine_friendly=True,
                ),
                ExampleSpec(
                    id="init_common",
                    title="JSON 模式初始化",
                    category=ExampleCategory.COMMON,
                    command="flow-xhs --format json init",
                    machine_friendly=True,
                ),
                ExampleSpec(
                    id="init_automation",
                    title="自动化系统初始化",
                    category=ExampleCategory.AUTOMATION,
                    command="flow-xhs --format json --trace-id req-001 init",
                    machine_friendly=True,
                ),
            ),
            related_commands=("flow-xhs doctor", "flow-xhs account login"),
            help=CommandHelpSpec(
                section_order=(
                    "usage",
                    "summary",
                    "examples",
                )
            ),
        ),
        _command(
            id="doctor",
            path=("doctor",),
            summary="执行环境与依赖自检。",
            success_command="doctor",
            output=OutputSpec(
                success_command="doctor",
                success_schema_ref=SUCCESS_SCHEMA,
                error_schema_ref=ERROR_SCHEMA,
                data_shape_summary="诊断结果对象，包含整体状态和检查项。",
            ),
            examples=(
                ExampleSpec(
                    id="doctor_minimal",
                    title="执行自检",
                    category=ExampleCategory.MINIMAL,
                    command="flow-xhs doctor",
                    machine_friendly=True,
                ),
                ExampleSpec(
                    id="doctor_common",
                    title="JSON 模式自检",
                    category=ExampleCategory.COMMON,
                    command="flow-xhs --format json doctor",
                    machine_friendly=True,
                ),
                ExampleSpec(
                    id="doctor_automation",
                    title="自动化系统自检",
                    category=ExampleCategory.AUTOMATION,
                    command="flow-xhs --format json --trace-id req-001 doctor",
                    machine_friendly=True,
                ),
            ),
            related_commands=("flow-xhs init", "flow-xhs account login"),
            help=CommandHelpSpec(
                section_order=(
                    "usage",
                    "summary",
                    "examples",
                )
            ),
        ),
        _command(
            id="account_login",
            path=("account", "login"),
            summary="启动账号登录流程并写入持久登录态。",
            description=(
                "适用于首次登录、登录过期恢复或批量账号补登。"
            ),
            success_command="account.login",
            output=OutputSpec(
                success_command="account.login",
                success_schema_ref=SUCCESS_SCHEMA,
                error_schema_ref=ERROR_SCHEMA,
                data_shape_summary="登录结果对象，包含账号标识、模式和登录结果。",
                supports_events=True,
                event_channel="stderr",
                event_spec=EventSpec(
                    type_field="event",
                    events=(
                        EventTypeSpec(
                            name="login.qr_ready",
                            summary="二维码已准备好，可供扫码登录。",
                            payload_fields=("mode", "screenshot_path", "timeout_seconds"),
                        ),
                    ),
                ),
            ),
            parameters=(
                _command_option(
                    id="mode",
                    cli_name="--mode",
                    group=ParameterGroup.OPTIONAL_INPUTS,
                    summary="登录模式（local|remote）。",
                    description="local 在当前终端扫码；remote 用于远端会话并可输出二维码截图。",
                    value_kind=ValueKind.ENUM,
                    default=DefaultSpec(kind=DefaultKind.STATIC, value="local", display_value="local"),
                    allowed_values=tuple(AllowedValueSpec(value) for value in ACCOUNT_LOGIN_MODE_VALUES),
                ),
                _command_option(
                    id="login_timeout_seconds",
                    cli_name="--login-timeout-seconds",
                    group=ParameterGroup.EXECUTION_CONTROLS,
                    summary=f"登录超时秒数（最小 {ACCOUNT_LOGIN_TIMEOUT_MIN}）。",
                    description="remote 场景建议按会话交互时长设置，超时后需重新发起登录。",
                    value_kind=ValueKind.INTEGER,
                    min_value=ACCOUNT_LOGIN_TIMEOUT_MIN,
                    default=DefaultSpec(
                        kind=DefaultKind.STATIC,
                        value=ACCOUNT_LOGIN_TIMEOUT_DEFAULT,
                        display_value=str(ACCOUNT_LOGIN_TIMEOUT_DEFAULT),
                    ),
                ),
                _command_option(
                    id="screenshot_path",
                    cli_name="--screenshot-path",
                    group=ParameterGroup.EXECUTION_CONTROLS,
                    summary="remote 模式二维码截图路径。",
                    description="建议显式指定到任务工作目录，便于上游系统直接回传二维码图片。",
                    value_kind=ValueKind.PATH,
                ),
            ),
            constraints=(),
            examples=(
                ExampleSpec(
                    id="account_login_minimal",
                    title="本机扫码登录",
                    category=ExampleCategory.MINIMAL,
                    command="flow-xhs --format json account login",
                    machine_friendly=True,
                ),
                ExampleSpec(
                    id="account_login_remote",
                    title="远程扫码登录",
                    category=ExampleCategory.COMMON,
                    command="flow-xhs --format json account login --mode remote --screenshot-path /tmp/xhs-login.png",
                    machine_friendly=True,
                ),
                ExampleSpec(
                    id="account_login_automation",
                    title="自动化系统登录",
                    category=ExampleCategory.AUTOMATION,
                    command="flow-xhs --format json --trace-id req-001 account login --mode remote --login-timeout-seconds 300",
                    machine_friendly=True,
                ),
            ),
            related_commands=("flow-xhs account status", "flow-xhs account list"),
            help=CommandHelpSpec(
                usage_options_label="OPTIONS",
                section_order=(
                    "usage",
                    "summary",
                    "options",
                    "examples",
                ),
            ),
        ),
        _command(
            id="account_status",
            path=("account", "status"),
            summary="实时检查并刷新账号登录状态。",
            description="用于在搜索或发布前确认账号可用性。",
            success_command="account.status",
            output=OutputSpec(
                success_command="account.status",
                success_schema_ref=SUCCESS_SCHEMA,
                error_schema_ref=ERROR_SCHEMA,
                data_shape_summary="账号状态列表对象。",
            ),
            examples=(
                ExampleSpec(
                    id="account_status_minimal",
                    title="检查全部账号状态",
                    category=ExampleCategory.MINIMAL,
                    command="flow-xhs --format json account status",
                    machine_friendly=True,
                ),
                ExampleSpec(
                    id="account_status_common",
                    title="检查账号状态并查看当前环境标记",
                    category=ExampleCategory.COMMON,
                    command="flow-xhs --format json account status --out account-status.json",
                    machine_friendly=True,
                ),
                ExampleSpec(
                    id="account_status_automation",
                    title="自动化系统检查账号状态",
                    category=ExampleCategory.AUTOMATION,
                    command="flow-xhs --format json --trace-id req-001 account status",
                    machine_friendly=True,
                ),
            ),
            related_commands=("flow-xhs account login", "flow-xhs account list"),
            help=CommandHelpSpec(
                section_order=(
                    "usage",
                    "summary",
                    "examples",
                )
            ),
        ),
        _command(
            id="account_list",
            path=("account", "list"),
            summary="列出账号池。",
            description="默认仅返回可用账号；可通过 `--only-active false` 查看全部账号。",
            success_command="account.list",
            parameters=(
                _command_option(
                    id="only_active",
                    cli_name="--only-active",
                    group=ParameterGroup.OPTIONAL_INPUTS,
                    summary="是否仅展示可用账号。",
                    description="true 仅返回可执行账号；false 返回全部账号，便于排查历史账号状态。",
                    value_kind=ValueKind.ENUM,
                    default=DefaultSpec(kind=DefaultKind.STATIC, value="true", display_value="true"),
                    allowed_values=tuple(AllowedValueSpec(value) for value in BOOLEAN_LITERAL_VALUES),
                ),
            ),
            output=OutputSpec(
                success_command="account.list",
                success_schema_ref=SUCCESS_SCHEMA,
                error_schema_ref=ERROR_SCHEMA,
                data_shape_summary="账号池列表对象。",
            ),
            examples=(
                ExampleSpec(
                    id="account_list_minimal",
                    title="列出可用账号",
                    category=ExampleCategory.MINIMAL,
                    command="flow-xhs --format json account list",
                    machine_friendly=True,
                ),
                ExampleSpec(
                    id="account_list_common",
                    title="列出全部账号",
                    category=ExampleCategory.COMMON,
                    command="flow-xhs --format json account list --only-active false",
                    machine_friendly=True,
                ),
                ExampleSpec(
                    id="account_list_automation",
                    title="自动化系统列账号",
                    category=ExampleCategory.AUTOMATION,
                    command="flow-xhs --format json --trace-id req-001 account list",
                    machine_friendly=True,
                ),
            ),
            related_commands=("flow-xhs account status", "flow-xhs account activate"),
            help=CommandHelpSpec(
                usage_options_label="OPTIONS",
                section_order=(
                    "usage",
                    "summary",
                    "options",
                    "examples",
                ),
            ),
        ),
        _command(
            id="account_activate",
            path=("account", "activate"),
            summary="设置当前账号环境。",
            description="将指定账号设为当前执行环境；后续需要登录态的命令默认使用该账号。",
            success_command="account.activate",
            parameters=(
                _command_option(
                    id="account",
                    cli_name="--account",
                    group=ParameterGroup.REQUIRED_INPUTS,
                    summary="账号唯一标识。",
                    description="可通过 `flow-xhs --format json account list` 获取候选账号 ID。",
                    required=True,
                    nullable=False,
                ),
            ),
            output=OutputSpec(
                success_command="account.activate",
                success_schema_ref=SUCCESS_SCHEMA,
                error_schema_ref=ERROR_SCHEMA,
                data_shape_summary="账号状态变更结果对象。",
            ),
            examples=(
                ExampleSpec(
                    id="account_activate_minimal",
                    title="切换当前账号",
                    category=ExampleCategory.MINIMAL,
                    command="flow-xhs --format json account activate --account <account_uid>",
                    machine_friendly=True,
                ),
                ExampleSpec(
                    id="account_activate_common",
                    title="切换当前账号并带 trace_id",
                    category=ExampleCategory.COMMON,
                    command="flow-xhs --format json --trace-id req-001 account activate --account <account_uid>",
                    machine_friendly=True,
                ),
                ExampleSpec(
                    id="account_activate_automation",
                    title="自动化系统切换当前账号",
                    category=ExampleCategory.AUTOMATION,
                    command="flow-xhs --format json --trace-id req-activate-001 account activate --account <account_uid> --out activate-result.json",
                    machine_friendly=True,
                ),
            ),
            related_commands=("flow-xhs account list", "flow-xhs user self"),
            help=CommandHelpSpec(
                usage_options_label="OPTIONS",
                section_order=(
                    "usage",
                    "summary",
                    "options",
                    "examples",
                ),
            ),
        ),
        _command(
            id="account_delete",
            path=("account", "delete"),
            summary="删除账号记录。",
            description="从账号池中移除指定账号，仅影响本地持久记录，不会触发平台侧注销。",
            success_command="account.delete",
            parameters=(
                _command_option(
                    id="account",
                    cli_name="--account",
                    group=ParameterGroup.REQUIRED_INPUTS,
                    summary="账号唯一标识。",
                    description="删除前建议先执行 account status/list 确认目标账号，避免误删当前执行账号。",
                    required=True,
                    nullable=False,
                ),
            ),
            output=OutputSpec(
                success_command="account.delete",
                success_schema_ref=SUCCESS_SCHEMA,
                error_schema_ref=ERROR_SCHEMA,
                data_shape_summary="账号删除结果对象。",
            ),
            examples=(
                ExampleSpec(
                    id="account_delete_minimal",
                    title="删除账号",
                    category=ExampleCategory.MINIMAL,
                    command="flow-xhs --format json account delete --account <account_uid>",
                    machine_friendly=True,
                ),
                ExampleSpec(
                    id="account_delete_common",
                    title="删除账号并带 trace_id",
                    category=ExampleCategory.COMMON,
                    command="flow-xhs --format json --trace-id req-001 account delete --account <account_uid>",
                    machine_friendly=True,
                ),
                ExampleSpec(
                    id="account_delete_automation",
                    title="自动化系统删除账号",
                    category=ExampleCategory.AUTOMATION,
                    command="flow-xhs --format json --trace-id req-delete-001 account delete --account <account_uid> --out delete-result.json",
                    machine_friendly=True,
                ),
            ),
            related_commands=("flow-xhs account list", "flow-xhs account activate"),
            help=CommandHelpSpec(
                usage_options_label="OPTIONS",
                section_order=(
                    "usage",
                    "summary",
                    "options",
                    "examples",
                ),
            ),
        ),
        _command(
            id="note_get",
            path=("note", "get"),
            summary="获取单条笔记详情与评论。",
            description=None,
            success_command="note.get",
            parameters=(
                _command_option(
                    id="note_url",
                    cli_name="--note-url",
                    group=ParameterGroup.REQUIRED_INPUTS,
                    summary="笔记详情 URL。",
                    description="推荐直接传入完整笔记链接，自动解析 note_id、xsec_token、xsec_source。",
                    required=True,
                ),
                _command_option(
                    id="comment_size",
                    cli_name="--comment-size",
                    group=ParameterGroup.OPTIONAL_INPUTS,
                    summary=f"一级评论数量。",
                    description="用于控制评论抓取规模；数值越大耗时越长。",
                    value_kind=ValueKind.INTEGER,
                    min_value=NOTE_GET_COMMENT_SIZE_MIN,
                    default=DefaultSpec(
                        kind=DefaultKind.STATIC,
                        value=NOTE_GET_COMMENT_SIZE_DEFAULT,
                        display_value=str(NOTE_GET_COMMENT_SIZE_DEFAULT),
                    ),
                ),
                _command_option(
                    id="sub_comment_size",
                    cli_name="--sub-comment-size",
                    group=ParameterGroup.OPTIONAL_INPUTS,
                    summary=f"二级评论数量。",
                    description="每条一级评论可抓取的二级评论上限；用于平衡数据量与时延。",
                    value_kind=ValueKind.INTEGER,
                    min_value=NOTE_GET_SUB_COMMENT_SIZE_MIN,
                    default=DefaultSpec(
                        kind=DefaultKind.STATIC,
                        value=NOTE_GET_SUB_COMMENT_SIZE_DEFAULT,
                        display_value=str(NOTE_GET_SUB_COMMENT_SIZE_DEFAULT),
                    ),
                ),
                _input_source_option(
                    summary="JSON 输入（文件路径或标准输入）。",
                    fields="note_url,comment_size,sub_comment_size",
                    description=(
                        "字段示例：note_url,comment_size,sub_comment_size。"
                    ),
                ),
            ),
            constraints=(),
            output=OutputSpec(
                success_command="note.get",
                success_schema_ref=SUCCESS_SCHEMA,
                error_schema_ref=ERROR_SCHEMA,
                data_shape_summary="单条笔记详情对象，包含评论信息。",
            ),
            examples=(
                ExampleSpec(
                    id="note_get_minimal",
                    title="最小笔记详情示例",
                    category=ExampleCategory.MINIMAL,
                    command="flow-xhs --format json note get --note-url https://www.xiaohongshu.com/explore/<note_id>?xsec_source=<xsec_source>",
                    machine_friendly=True,
                ),
                ExampleSpec(
                    id="note_get_common",
                    title="搜索结果回传笔记链接",
                    category=ExampleCategory.COMMON,
                    command="flow-xhs --format json note get --note-url https://www.xiaohongshu.com/explore/<note_id>?xsec_token=<xsec_token>&xsec_source=<xsec_source>",
                    machine_friendly=True,
                ),
                ExampleSpec(
                    id="note_get_automation",
                    title="从输入流获取笔记详情",
                    category=ExampleCategory.AUTOMATION,
                    command="cat payload.json | flow-xhs --format json note get --input -",
                    machine_friendly=True,
                ),
            ),
            related_commands=("flow-xhs note search", "flow-xhs user get"),
            help=CommandHelpSpec(
                usage_options_token="[OPTIONS]",
                section_order=(
                    "usage",
                    "summary",
                    "options",
                    "examples",
                ),
            ),
        ),
        _command(
            id="note_search",
            path=("note", "search"),
            summary="搜索笔记列表。",
            description=None,
            success_command="note.search",
            parameters=(
                _command_option(
                    id="keyword",
                    cli_name="--keyword",
                    group=ParameterGroup.REQUIRED_INPUTS,
                    summary="搜索关键词。",
                    description="建议传入明确主题词（如产品名、场景词），以降低噪声结果比例。",
                    required=True,
                ),
                _command_option(
                    id="size",
                    cli_name="--size",
                    group=ParameterGroup.OPTIONAL_INPUTS,
                    summary=f"返回数量。",
                    description="单次返回条数，适合按批次拉取并在上游做去重与再排序。",
                    value_kind=ValueKind.INTEGER,
                    min_value=NOTE_SEARCH_SIZE_MIN,
                    default=DefaultSpec(
                        kind=DefaultKind.STATIC,
                        value=NOTE_SEARCH_SIZE_DEFAULT,
                        display_value=str(NOTE_SEARCH_SIZE_DEFAULT),
                    ),
                ),
                _command_option(
                    id="sort_by",
                    cli_name="--sort-by",
                    group=ParameterGroup.OPTIONAL_INPUTS,
                    summary="排序方式。",
                    description="默认综合排序；若关注时效建议使用 latest。",
                    value_kind=ValueKind.ENUM,
                    default=DefaultSpec(kind=DefaultKind.STATIC, value="comprehensive", display_value="comprehensive"),
                    allowed_values=_filter_allowed_values("sort_by"),
                ),
                _command_option(
                    id="note_type",
                    cli_name="--note-type",
                    group=ParameterGroup.OPTIONAL_INPUTS,
                    summary="内容类型过滤。",
                    description="用于限定图文或视频，减少后续二次过滤成本。",
                    value_kind=ValueKind.ENUM,
                    default=DefaultSpec(kind=DefaultKind.STATIC, value="all", display_value="all"),
                    allowed_values=_filter_allowed_values("note_type"),
                ),
                _command_option(
                    id="publish_time",
                    cli_name="--publish-time",
                    group=ParameterGroup.OPTIONAL_INPUTS,
                    summary="发布时间过滤。",
                    description="用于限制结果时窗，便于做近期热点或历史复盘。",
                    value_kind=ValueKind.ENUM,
                    default=DefaultSpec(kind=DefaultKind.STATIC, value="all", display_value="all"),
                    allowed_values=_filter_allowed_values("publish_time"),
                ),
                _command_option(
                    id="search_scope",
                    cli_name="--search-scope",
                    group=ParameterGroup.OPTIONAL_INPUTS,
                    summary="搜索范围过滤。",
                    description="可切换全部、已关注、已看过、未看过范围。",
                    value_kind=ValueKind.ENUM,
                    default=DefaultSpec(kind=DefaultKind.STATIC, value="all", display_value="all"),
                    allowed_values=_filter_allowed_values("search_scope"),
                ),
                _command_option(
                    id="location",
                    cli_name="--location",
                    group=ParameterGroup.OPTIONAL_INPUTS,
                    summary="地理范围过滤。",
                    description="用于同城/附近等地域过滤；未指定时按平台默认范围搜索。",
                    value_kind=ValueKind.ENUM,
                    default=DefaultSpec(kind=DefaultKind.STATIC, value="all", display_value="all"),
                    allowed_values=_filter_allowed_values("location"),
                ),
                _input_source_option(
                    summary="JSON 输入（文件路径或标准输入）。",
                    fields="keyword,size,sort_by,note_type,publish_time,search_scope,location",
                    description="字段示例：keyword,size,sort_by,note_type,publish_time,search_scope,location。",
                ),
            ),
            constraints=(),
            examples=(
                ExampleSpec(
                    id="note_search_minimal",
                    title="最小搜索示例",
                    category=ExampleCategory.MINIMAL,
                    command="flow-xhs --format json note search --keyword 摄影",
                    machine_friendly=True,
                ),
                ExampleSpec(
                    id="note_search_common",
                    title="带筛选的搜索示例",
                    category=ExampleCategory.COMMON,
                    command="flow-xhs --format json note search --keyword 摄影 --size 20 --sort-by latest --note-type image_text",
                    machine_friendly=True,
                ),
                ExampleSpec(
                    id="note_search_automation",
                    title="从输入文件搜索",
                    category=ExampleCategory.AUTOMATION,
                    command="cat payload.json | flow-xhs --format json note search --input -",
                    machine_friendly=True,
                ),
            ),
            related_commands=("flow-xhs note get", "flow-xhs user search"),
            help=CommandHelpSpec(
                usage_options_token="[OPTIONS]",
                section_order=(
                    "usage",
                    "summary",
                    "options",
                    "examples",
                ),
            ),
            output=OutputSpec(
                success_command="note.search",
                success_schema_ref=SUCCESS_SCHEMA,
                error_schema_ref=ERROR_SCHEMA,
                data_shape_summary="笔记搜索结果列表对象。",
            ),
        ),
        _command(
            id="note_publish",
            path=("note", "publish"),
            summary="发布图文或视频笔记。",
            description=None,
            success_command="note.publish",
            parameters=(
                NOTE_PUBLISH_TARGET,
                ParameterSpec(
                    id="image_list",
                    name="image_list",
                    cli_names=("--image-list",),
                    scope=ParameterScope.COMMAND,
                    kind=ParameterKind.OPTION,
                    group=ParameterGroup.CONDITIONAL_INPUTS,
                    summary="图片路径或 URL 列表。",
                    description="用于图文发布素材输入；支持 CSV，本地路径与远程 URL 可混合。",
                    value_type=ValueTypeSpec(kind=ValueKind.ARRAY, item_kind=ValueKind.STRING, separator=",", nullable=True),
                    requiredness=RequirednessSpec(
                        mode=RequirednessMode.CONDITIONAL,
                        condition=ConditionExpr(op="eq", field="target", value="image"),
                        message="当 --target=image 时必须提供 --image-list。",
                    ),
                    input_bindings=(
                        InputSourceBinding(source=InputSourceKind.CLI, priority=1),
                        InputSourceBinding(source=InputSourceKind.INPUT_JSON, field_name="image_list", priority=2),
                    ),
                ),
                ParameterSpec(
                    id="video",
                    name="video",
                    cli_names=("--video",),
                    scope=ParameterScope.COMMAND,
                    kind=ParameterKind.OPTION,
                    group=ParameterGroup.CONDITIONAL_INPUTS,
                    summary="视频路径或 URL。",
                    description="用于视频发布主素材。",
                    value_type=ValueTypeSpec(kind=ValueKind.STRING, nullable=True),
                    requiredness=RequirednessSpec(
                        mode=RequirednessMode.CONDITIONAL,
                        condition=ConditionExpr(op="eq", field="target", value="video"),
                        message="当 --target=video 时必须提供 --video。",
                    ),
                    input_bindings=(
                        InputSourceBinding(source=InputSourceKind.CLI, priority=1),
                        InputSourceBinding(source=InputSourceKind.INPUT_JSON, field_name="video", priority=2),
                    ),
                ),
                _command_option(
                    id="title",
                    cli_name="--title",
                    group=ParameterGroup.REQUIRED_INPUTS,
                    summary="标题。",
                    description="标题文本；建议控制在平台允许范围内。",
                    required=True,
                ),
                _command_option(
                    id="content",
                    cli_name="--content",
                    group=ParameterGroup.REQUIRED_INPUTS,
                    summary="正文。",
                    description="正文文案；建议在上游控制长度并避免触发平台风控词。",
                    required=True,
                ),
                ParameterSpec(
                    id="tags",
                    name="tags",
                    cli_names=("--tags",),
                    scope=ParameterScope.COMMAND,
                    kind=ParameterKind.OPTION,
                    group=ParameterGroup.OPTIONAL_INPUTS,
                    summary="标签列表（CSV）。",
                    description="支持 CSV 输入，`--input` 中也支持 JSON 数组。",
                    value_type=ValueTypeSpec(kind=ValueKind.ARRAY, item_kind=ValueKind.STRING, separator=",", nullable=True),
                    requiredness=RequirednessSpec(mode=RequirednessMode.OPTIONAL),
                    input_bindings=(
                        InputSourceBinding(source=InputSourceKind.CLI, priority=1),
                        InputSourceBinding(source=InputSourceKind.INPUT_JSON, field_name="tags", priority=2),
                    ),
                ),
                ParameterSpec(
                    id="schedule_at",
                    name="schedule_at",
                    cli_names=("--schedule-at",),
                    scope=ParameterScope.COMMAND,
                    kind=ParameterKind.OPTION,
                    group=ParameterGroup.OPTIONAL_INPUTS,
                    summary="定时发布时间，需为带时区 RFC3339，且时间在 1 小时后至 14 天内。",
                    description="若提供，必须符合 RFC3339 并包含时区。",
                    value_type=ValueTypeSpec(kind=ValueKind.TIMESTAMP, format="rfc3339", nullable=True),
                    requiredness=RequirednessSpec(mode=RequirednessMode.OPTIONAL),
                    input_bindings=(
                        InputSourceBinding(source=InputSourceKind.CLI, priority=1),
                        InputSourceBinding(source=InputSourceKind.INPUT_JSON, field_name="schedule_at", priority=2),
                    ),
                ),
                _input_source_option(
                    summary="JSON 输入（文件路径或标准输入）。",
                    fields="target,image_list,video,title,content,tags,schedule_at",
                    description="字段示例：target,image_list,video,title,content,tags,schedule_at。",
                ),
            ),
            constraints=(),
            examples=(
                ExampleSpec(
                    id="note_publish_minimal_image",
                    title="发布最小图文示例",
                    category=ExampleCategory.MINIMAL,
                    command="flow-xhs --format json note publish --target image --image-list a.jpg --title 标题 --content 正文",
                    machine_friendly=True,
                ),
                ExampleSpec(
                    id="note_publish_common_video",
                    title="发布视频示例",
                    category=ExampleCategory.COMMON,
                    command="flow-xhs --format json note publish --target video --video a.mp4 --title 标题 --content 正文",
                    machine_friendly=True,
                ),
                ExampleSpec(
                    id="note_publish_automation",
                    title="从输入流发布",
                    category=ExampleCategory.AUTOMATION,
                    command="cat payload.json | flow-xhs --format json note publish --input -",
                    machine_friendly=True,
                ),
            ),
            related_commands=("flow-xhs account login", "flow-xhs account status"),
            help=CommandHelpSpec(
                usage_options_token="[OPTIONS]",
                section_order=(
                    "usage",
                    "summary",
                    "options",
                    "examples",
                ),
            ),
            output=OutputSpec(
                success_command="note.publish",
                success_schema_ref=SUCCESS_SCHEMA,
                error_schema_ref=ERROR_SCHEMA,
                data_shape_summary="发布结果对象，至少包含内容 ID 或发布任务结果。",
            ),
        ),
        _command(
            id="user_get",
            path=("user", "get"),
            summary="获取单个用户主页详情。",
            description=None,
            success_command="user.get",
            parameters=(
                _command_option(
                    id="user_url",
                    cli_name="--user-url",
                    group=ParameterGroup.REQUIRED_INPUTS,
                    summary="用户主页 URL。",
                    description="推荐直接传入完整用户链接，自动解析 user_id、xsec_token、xsec_source。",
                    required=True,
                ),
                _input_source_option(
                    summary="JSON 输入（文件路径或标准输入）。",
                    fields="user_url",
                    description="字段示例：user_url。",
                ),
            ),
            constraints=(),
            examples=(
                ExampleSpec(
                    id="user_get_minimal",
                    title="最小用户详情示例",
                    category=ExampleCategory.MINIMAL,
                    command="flow-xhs --format json user get --user-url https://www.xiaohongshu.com/user/profile/<user_id>?xsec_source=<xsec_source>",
                    machine_friendly=True,
                ),
                ExampleSpec(
                    id="user_get_common",
                    title="笔记作者详情示例",
                    category=ExampleCategory.COMMON,
                    command="flow-xhs --format json user get --user-url https://www.xiaohongshu.com/user/profile/<user_id>?xsec_token=<xsec_token>&xsec_source=<xsec_source>",
                    machine_friendly=True,
                ),
                ExampleSpec(
                    id="user_get_automation",
                    title="从输入文件获取用户详情",
                    category=ExampleCategory.AUTOMATION,
                    command="cat payload.json | flow-xhs --format json user get --input -",
                    machine_friendly=True,
                ),
            ),
            related_commands=("flow-xhs user search", "flow-xhs note get"),
            help=CommandHelpSpec(
                usage_options_token="[OPTIONS]",
                section_order=(
                    "usage",
                    "summary",
                    "options",
                    "examples",
                ),
            ),
            output=OutputSpec(
                success_command="user.get",
                success_schema_ref=SUCCESS_SCHEMA,
                error_schema_ref=ERROR_SCHEMA,
                data_shape_summary="单个用户主页详情对象。",
            ),
        ),
        _command(
            id="user_search",
            path=("user", "search"),
            summary="搜索用户列表。",
            description=None,
            success_command="user.search",
            parameters=(
                _command_option(
                    id="keyword",
                    cli_name="--keyword",
                    group=ParameterGroup.REQUIRED_INPUTS,
                    summary="搜索关键词。",
                    description="建议使用垂类关键词或达人画像词，提高搜索结果可用性。",
                    required=True,
                ),
                _command_option(
                    id="size",
                    cli_name="--size",
                    group=ParameterGroup.OPTIONAL_INPUTS,
                    summary=f"返回数量。",
                    description="单次返回条数，建议与上游分页或去重策略配合使用。",
                    value_kind=ValueKind.INTEGER,
                    min_value=USER_SEARCH_SIZE_MIN,
                    default=DefaultSpec(
                        kind=DefaultKind.STATIC,
                        value=USER_SEARCH_SIZE_DEFAULT,
                        display_value=str(USER_SEARCH_SIZE_DEFAULT),
                    ),
                ),
                _input_source_option(
                    summary="JSON 输入（文件路径或标准输入）。",
                    fields="keyword,size",
                    description="字段示例：keyword,size。",
                ),
            ),
            constraints=(),
            examples=(
                ExampleSpec(
                    id="user_search_minimal",
                    title="最小用户搜索示例",
                    category=ExampleCategory.MINIMAL,
                    command="flow-xhs --format json user search --keyword 摄影",
                    machine_friendly=True,
                ),
                ExampleSpec(
                    id="user_search_common",
                    title="常见用户搜索示例",
                    category=ExampleCategory.COMMON,
                    command="flow-xhs --format json user search --keyword 摄影 --size 20",
                    machine_friendly=True,
                ),
                ExampleSpec(
                    id="user_search_automation",
                    title="从输入流搜索用户",
                    category=ExampleCategory.AUTOMATION,
                    command="cat payload.json | flow-xhs --format json user search --input -",
                    machine_friendly=True,
                ),
            ),
            related_commands=("flow-xhs note search", "flow-xhs user get"),
            help=CommandHelpSpec(
                usage_options_token="[OPTIONS]",
                section_order=(
                    "usage",
                    "summary",
                    "options",
                    "examples",
                ),
            ),
            output=OutputSpec(
                success_command="user.search",
                success_schema_ref=SUCCESS_SCHEMA,
                error_schema_ref=ERROR_SCHEMA,
                data_shape_summary="用户搜索结果列表对象。",
            ),
        ),
        _command(
            id="user_self",
            path=("user", "self"),
            summary="获取当前登录账号对应的用户信息。",
            description=None,
            success_command="user.self",
            examples=(
                ExampleSpec(
                    id="user_self_minimal",
                    title="查询当前账号自身信息",
                    category=ExampleCategory.MINIMAL,
                    command="flow-xhs --format json user self",
                    machine_friendly=True,
                ),
                ExampleSpec(
                    id="user_self_common",
                    title="带 trace_id 查询自身信息",
                    category=ExampleCategory.COMMON,
                    command="flow-xhs --format json --trace-id req-001 user self",
                    machine_friendly=True,
                ),
                ExampleSpec(
                    id="user_self_automation",
                    title="自动化系统查询自身信息",
                    category=ExampleCategory.AUTOMATION,
                    command="flow-xhs --format json --trace-id req-self-001 user self --out self-result.json",
                    machine_friendly=True,
                ),
            ),
            related_commands=("flow-xhs account status", "flow-xhs user get"),
            help=CommandHelpSpec(
                section_order=(
                    "usage",
                    "summary",
                    "examples",
                )
            ),
            output=OutputSpec(
                success_command="user.self",
                success_schema_ref=SUCCESS_SCHEMA,
                error_schema_ref=ERROR_SCHEMA,
                data_shape_summary="当前登录账号对应的用户信息对象。",
            ),
        ),
    ),
    topics=(),
    metadata={
        "quick_start": (
            "flow-xhs init",
            "flow-xhs --format json doctor",
            "flow-xhs --format json note search --keyword 摄影 --size 20",
            "flow-xhs --format json note get --note-url <url>",
        ),
        "groups": {
            ("account",): {
                "summary": "账号管理命令。",
                "description": "用于登录、检查状态、切换账号与清理账号记录。",
                "use_cases": (
                    "flow-xhs --format json account login",
                    "flow-xhs --format json account status",
                ),
            },
            ("note",): {
                "summary": "笔记获取、搜索与发布命令。",
                "description": "用于获取笔记详情、按关键词搜索与发布。",
                "use_cases": (
                    "flow-xhs --format json note get --note-url <url>",
                    "flow-xhs --format json note search --keyword 摄影",
                    "flow-xhs --format json note publish --target image --image-list a.jpg",
                ),
            },
            ("user",): {
                "summary": "用户获取与搜索命令。",
                "description": "用于获取用户详情、按关键词搜索和当前账号自查。",
                "use_cases": (
                    "flow-xhs --format json user get --user-url <url>",
                    "flow-xhs --format json user search --keyword 摄影 --size 20",
                    "flow-xhs --format json user self",
                ),
            },
        }
    },
)


validate_cli_spec(FLOW_XHS_SPEC)
