from __future__ import annotations

import typer

from flow_xhs.cli.spec.runtime_contracts import (
    command_option,
    emit_command_help_if_empty,
)
from flow_xhs.contracts.command_inputs import NoteSearchInput, UserSearchInput
from flow_xhs.services.note_search import execute_note_search
from flow_xhs.services.user_search import execute_user_search
from flow_xhs.cli.context import CliContext
from flow_xhs.cli.runtime import run_async_command
from flow_xhs.cli.utils import load_json_input, pick_cli_or_input, resolve_account_uid


def run_note_search(
    *,
    ctx: typer.Context,
    keyword: str | None = command_option(("note", "search"), "keyword", None),
    size: int | None = command_option(("note", "search"), "size"),
    sort_by: str | None = command_option(("note", "search"), "sort_by", None),
    note_type: str | None = command_option(("note", "search"), "note_type", None),
    publish_time: str | None = command_option(("note", "search"), "publish_time", None),
    search_scope: str | None = command_option(("note", "search"), "search_scope", None),
    location: str | None = command_option(("note", "search"), "location", None),
    input_file: str | None = command_option(("note", "search"), "input", None),
):
    emit_command_help_if_empty(ctx, ("note", "search"))

    cli_ctx: CliContext = ctx.obj
    payload = load_json_input(input_file)
    resolved_account_uid: str | None = None

    async def _run():
        nonlocal resolved_account_uid
        resolved_account_uid = resolve_account_uid()
        validated = NoteSearchInput(
            keyword=pick_cli_or_input(
                ctx=ctx,
                param_name="keyword",
                cli_value=keyword,
                payload=payload,
                payload_key="keyword",
            ),
            size=pick_cli_or_input(
                ctx=ctx,
                param_name="size",
                cli_value=size,
                payload=payload,
                payload_key="size",
            ),
            sort_by=pick_cli_or_input(
                ctx=ctx,
                param_name="sort_by",
                cli_value=sort_by,
                payload=payload,
                payload_key="sort_by",
            ),
            note_type=pick_cli_or_input(
                ctx=ctx,
                param_name="note_type",
                cli_value=note_type,
                payload=payload,
                payload_key="note_type",
            ),
            publish_time=pick_cli_or_input(
                ctx=ctx,
                param_name="publish_time",
                cli_value=publish_time,
                payload=payload,
                payload_key="publish_time",
            ),
            search_scope=pick_cli_or_input(
                ctx=ctx,
                param_name="search_scope",
                cli_value=search_scope,
                payload=payload,
                payload_key="search_scope",
            ),
            location=pick_cli_or_input(
                ctx=ctx,
                param_name="location",
                cli_value=location,
                payload=payload,
                payload_key="location",
            ),
            account_uid=resolved_account_uid,
        )
        return await execute_note_search(
            keyword=validated.keyword,
            size=validated.size,
            sort_by=validated.sort_by,
            note_type=validated.note_type,
            publish_time=validated.publish_time,
            search_scope=validated.search_scope,
            location=validated.location,
            account_uid=validated.account_uid,
        )

    run_async_command(
        ctx=cli_ctx,
        command="note.search",
        func=_run,
        account_uid=lambda: resolved_account_uid,
    )


def run_user_search(
    *,
    ctx: typer.Context,
    keyword: str | None = command_option(("user", "search"), "keyword", None),
    size: int | None = command_option(("user", "search"), "size"),
    input_file: str | None = command_option(("user", "search"), "input", None),
):
    emit_command_help_if_empty(ctx, ("user", "search"))

    cli_ctx: CliContext = ctx.obj
    payload = load_json_input(input_file)
    resolved_account_uid: str | None = None

    async def _run():
        nonlocal resolved_account_uid
        resolved_account_uid = resolve_account_uid()
        validated = UserSearchInput(
            keyword=pick_cli_or_input(
                ctx=ctx,
                param_name="keyword",
                cli_value=keyword,
                payload=payload,
                payload_key="keyword",
            ),
            size=pick_cli_or_input(
                ctx=ctx,
                param_name="size",
                cli_value=size,
                payload=payload,
                payload_key="size",
            ),
            account_uid=resolved_account_uid,
        )
        return await execute_user_search(
            keyword=validated.keyword,
            size=validated.size,
            account_uid=validated.account_uid,
        )

    run_async_command(
        ctx=cli_ctx,
        command="user.search",
        func=_run,
        account_uid=lambda: resolved_account_uid,
    )
