from __future__ import annotations

import typer

from flow_xhs.contracts.command_inputs import PublishNoteInput
from flow_xhs.services.publish_note import execute_publish_note
from flow_xhs.cli.context import CliContext
from flow_xhs.cli.runtime import run_async_command
from flow_xhs.cli.utils import all_option_params_are_default, load_json_input, parse_csv, pick_cli_or_input
from flow_xhs.errors import InvalidArgsError


app = typer.Typer(help="发布相关命令（图文/视频）", no_args_is_help=False)


@app.callback(invoke_without_command=True)
def publish(
    ctx: typer.Context,
    target: str | None = typer.Option("image", "--target", help="发布类型：image | video | article"),
    image_list: str | None = typer.Option(None, "--image-list", help="图片路径/URL 列表（逗号分隔，target=image 时必填）"),
    video: str | None = typer.Option(None, "--video", help="视频路径/URL（target=video 时必填）"),
    title: str | None = typer.Option(None, "--title", help="标题；可由 --input 提供"),
    content: str | None = typer.Option(None, "--content", help="正文；可由 --input 提供"),
    tags: str | None = typer.Option(None, "--tags", help="标签列表（逗号分隔），例如 科技,AI"),
    schedule_at: str | None = typer.Option(None, "--schedule-at", help="定时发布时间（RFC3339），为空表示立即发布"),
    account: str | None = typer.Option(None, "--account", help="账号唯一标识（user_no），必填"),
    input_file: str | None = typer.Option(
        None,
        "--input",
        help="JSON 输入文件路径或 '-'，字段示例：target,image_list,video,title,content,tags,schedule_at",
    ),
):
    """
    发布内容（图文/视频）。

    参数优先级：显式 CLI 参数 > --input JSON > 默认值。
    """
    if all_option_params_are_default(ctx=ctx):
        typer.echo(ctx.get_help())
        raise typer.Exit(code=0)

    cli_ctx: CliContext = ctx.obj
    payload = load_json_input(input_file)
    account_uid = (account or "").strip()

    async def _run():
        if not account_uid:
            raise InvalidArgsError("`--account` 为必填参数")

        resolved_target = pick_cli_or_input(
            ctx=ctx,
            param_name="target",
            cli_value=target,
            payload=payload,
            payload_key="target",
        )

        image_source = pick_cli_or_input(
            ctx=ctx,
            param_name="image_list",
            cli_value=image_list,
            payload=payload,
            payload_key="image_list",
        )
        if isinstance(image_source, list):
            raw_images = image_source
        else:
            raw_images = parse_csv(image_source)

        video_source = pick_cli_or_input(
            ctx=ctx,
            param_name="video",
            cli_value=video,
            payload=payload,
            payload_key="video",
        )
        normalized_video = video_source
        if isinstance(resolved_target, str) and resolved_target.strip().lower() == "video":
            if (normalized_video is None or normalized_video == "") and len(raw_images) == 1:
                normalized_video = raw_images[0]

        tags_source = pick_cli_or_input(
            ctx=ctx,
            param_name="tags",
            cli_value=tags,
            payload=payload,
            payload_key="tags",
        )
        if isinstance(tags_source, list):
            normalized_tags = tags_source
        else:
            normalized_tags = parse_csv(tags_source)

        validated = PublishNoteInput(
            target=resolved_target,
            image_list=raw_images,
            video=normalized_video,
            title=pick_cli_or_input(
                ctx=ctx,
                param_name="title",
                cli_value=title,
                payload=payload,
                payload_key="title",
            )
            or "",
            content=pick_cli_or_input(
                ctx=ctx,
                param_name="content",
                cli_value=content,
                payload=payload,
                payload_key="content",
            )
            or "",
            tags=normalized_tags,
            schedule_at=pick_cli_or_input(
                ctx=ctx,
                param_name="schedule_at",
                cli_value=schedule_at,
                payload=payload,
                payload_key="schedule_at",
            ),
            account_uid=account_uid,
        )
        target_text = validated.target.strip().lower()
        if target_text == "video":
            media_list = [validated.video] if validated.video else []
        elif target_text == "image":
            media_list = validated.image_list
        else:
            media_list = validated.image_list

        return await execute_publish_note(
            target=validated.target,
            image_list=media_list,
            title=validated.title,
            content=validated.content,
            tags=validated.tags,
            schedule_at=validated.schedule_at,
            account_uid=validated.account_uid,
        )

    run_async_command(
        ctx=cli_ctx,
        command="publish",
        func=_run,
        account_uid=account_uid,
    )
