"""Knowledge documents count command implementation."""

import json
from typing import Annotated, cast

import typer
from alloy_runtime_types.dtos.knowledge import CountDocumentsRequest, ProcessingStatus
from alloy_runtime_types.dtos.structured_filter import ConditionSpec, LogicalSpec
from pydantic import TypeAdapter, ValidationError

from cli.commands.knowledge.documents.count.presenter import present_documents_count
from cli.infrastructure.command import async_command, authenticated_client
from cli.infrastructure.file_content import resolve_content_or_raise


def _parse_metadata_filter(value: str | None) -> ConditionSpec | LogicalSpec | None:
    if value is None:
        return None
    resolved = (
        typer.get_text_stream("stdin").read()
        if value == "-"
        else resolve_content_or_raise(value)
    )
    if resolved is None:
        return None
    try:
        data = json.loads(resolved)
    except json.JSONDecodeError as error:
        typer.echo(f"Invalid JSON in --metadata-filter: {error}", err=True)
        raise typer.Exit(code=2) from error
    try:
        return cast(
            ConditionSpec | LogicalSpec,
            TypeAdapter(ConditionSpec | LogicalSpec).validate_python(data),
        )
    except ValidationError as error:
        typer.echo(f"Invalid metadata filter: {error}", err=True)
        raise typer.Exit(code=2) from error


def knowledge_documents_count_command(
    collection: Annotated[
        str | None,
        typer.Option("-C", "--collection", help="Filter by collection ID or name"),
    ] = None,
    status_: Annotated[
        str | None,
        typer.Option(
            "-s",
            "--status",
            help="Filter by status: queued|processing|completed|failed|duplicate|filtered",
        ),
    ] = None,
    external_id: Annotated[
        str | None, typer.Option("--external-id", help="Filter by external_id")
    ] = None,
    tag: Annotated[
        str | None, typer.Option("--tag", help="Filter by ltree tag pattern")
    ] = None,
    metadata_filter: Annotated[
        str | None,
        typer.Option(
            "--metadata-filter",
            help="Structured metadata filter JSON. Inline JSON, @file.json, @- or - for stdin.",
        ),
    ] = None,
    output_json: Annotated[bool, typer.Option("--json", help="Emit JSON")] = False,
) -> None:
    """Count documents matching combined filters."""
    request = CountDocumentsRequest(
        collection_id=collection,
        processing_status=cast(ProcessingStatus | None, status_),
        external_id=external_id,
        tag_filter=tag,
        metadata_filter=_parse_metadata_filter(metadata_filter),
    )
    _execute(request=request, output_json=output_json)


@async_command
async def _execute(*, request: CountDocumentsRequest, output_json: bool) -> None:
    async with authenticated_client() as (_config, client):
        response = await client.count_documents(request)
    present_documents_count(response, output_json=output_json)
