"""Pipeline executions list command implementation."""

import json
from typing import Annotated, Optional
from uuid import UUID

import typer

from cli.commands.flag_utils import validate_uuid
from cli.commands.pipelines.executions.presenter import present_executions_list
from cli.infrastructure.command import async_command, authenticated_client
from cli.infrastructure.file_content import FileContentError, resolve_content


def pipelines_executions_list_command(
    pipeline_id: str = typer.Argument(
        ...,
        help="Pipeline UUID",
    ),
    status: Optional[str] = typer.Option(
        None,
        "--status",
        help="Filter by status (pending, running, completed, failed)",
    ),
    external_id: Optional[str] = typer.Option(
        None,
        "--external-id",
        help="Filter by exact external_id",
    ),
    search: Optional[str] = typer.Option(
        None,
        "-s",
        "--search",
        help="Fuzzy search on external_id",
    ),
    tag: Annotated[
        list[str] | None,
        typer.Option(
            "--tag",
            help="Filter by tag path (repeatable, e.g., --tag pipeline.test)",
        ),
    ] = None,
    metadata_filter: Optional[str] = typer.Option(
        None,
        "--metadata-filter",
        help="Filter by metadata as JSON string or @file.json",
    ),
    limit: int = typer.Option(
        50,
        "-l",
        "--limit",
        min=1,
        max=100,
        help="Max results",
    ),
    offset: int = typer.Option(
        0,
        "--offset",
        min=0,
        help="Skip N results",
    ),
) -> None:
    """List executions for a pipeline.

    Examples:
        alloy pipelines executions list 123e4567-89ab...
        alloy pipelines executions list 123e4567-89ab... --status completed
        alloy pipelines executions list 123e4567-89ab... --tag pipeline.test --tag batch.weekly
        alloy pipelines executions list 123e4567-89ab... --metadata-filter '{"env": "prod"}'
    """
    pipeline_uuid = validate_uuid(pipeline_id, "pipeline")

    # Parse metadata_filter if provided
    metadata_filter_str: str | None = None
    if metadata_filter:
        try:
            resolved = resolve_content(metadata_filter)
        except FileContentError as e:
            raise typer.BadParameter(str(e))
        if resolved:
            try:
                json.loads(resolved)
            except json.JSONDecodeError as e:
                raise typer.BadParameter(f"Invalid JSON: {e}")
            metadata_filter_str = resolved

    _execute_list(
        pipeline_id=pipeline_uuid,
        status=status,
        external_id=external_id,
        search=search,
        tag_paths=tag,
        metadata_filter=metadata_filter_str,
        limit=limit,
        offset=offset,
    )


@async_command
async def _execute_list(
    pipeline_id: UUID,
    status: Optional[str],
    external_id: Optional[str],
    search: Optional[str],
    tag_paths: Optional[list[str]],
    metadata_filter: Optional[str],
    limit: int,
    offset: int,
) -> None:
    """Execute list executions operation."""
    async with authenticated_client() as (_config, client):
        response = await client.list_pipeline_executions(
            pipeline_id,
            status=status,
            external_id=external_id,
            search=search,
            tag_paths=tag_paths,
            metadata_filter=metadata_filter,
            limit=limit,
            offset=offset,
        )

    present_executions_list(response)
