"""Box (production box) CLI commands."""

from __future__ import annotations

from datetime import datetime
from pathlib import Path

import typer

from .client import QrmClient, QrmClientError
from .commands_shared import (
    CLI_DATE_FORMATS,
    OutputFormat,
    console,
    emit,
    format_api_datetime,
    load_state_or_exit,
    render_box_detail,
    render_box_list,
    render_uut_table,
    resolve_box_window,
)

box_app = typer.Typer(help="Inspect production boxes.")


@box_app.command("list")
def box_list(
    start: datetime | None = typer.Option(
        None,
        "--start",
        formats=CLI_DATE_FORMATS,
        help=(
            "Filter from this timestamp (UTC). Accepts ISO-8601 (e.g. 2020-01-01T00:00:00Z) "
            "or YYYY-MM-DD HH:MM:SS. Default: 1970-01-01T00:00:00Z."
        ),
    ),
    stop: datetime | None = typer.Option(
        None,
        "--stop",
        formats=CLI_DATE_FORMATS,
        help=(
            "Filter until this timestamp (UTC). Accepts ISO-8601 (e.g. 2026-02-06T23:59:00Z) "
            "or YYYY-MM-DD HH:MM:SS. Default: QRM current time."
        ),
    ),
    config_path: Path = typer.Option(
        None,
        "--config-path",
        help="Override the location of the login.json file.",
    ),
    base_url: str = typer.Option(
        None,
        "--base-url",
        help="Override the base URL stored in the config (useful for testing).",
    ),
    insecure: bool = typer.Option(
        False,
        "--insecure",
        help="Disable TLS verification when contacting QRM.",
    ),
    output: OutputFormat = typer.Option(
        OutputFormat.rich,
        "--output",
        "-o",
        case_sensitive=False,
        help="Choose output format: rich (default) or json.",
    ),
) -> None:
    """List production boxes via the `/Box/List` endpoint."""

    state = load_state_or_exit(config_path)
    resolved_start, resolved_stop = resolve_box_window(start, stop)

    client = QrmClient(
        base_url=base_url or str(state.base_url),
        verify_tls=not insecure and state.verify_tls,
    )

    try:
        payload = client.box_list(
            token=state.token,
            start_datetime=format_api_datetime(resolved_start),
            stop_datetime=(
                format_api_datetime(resolved_stop) if resolved_stop is not None else None
            ),
        )
    except QrmClientError as exc:
        typer.secho(f"Box list failed: {exc}", fg=typer.colors.RED)
        raise typer.Exit(code=1) from exc

    if output is OutputFormat.json:
        emit(payload, output)
        return

    console.print(render_box_list(payload))


@box_app.command("get")
def box_get(
    box_identifier: str = typer.Argument(..., help="Unique identifier for the production box."),
    config_path: Path = typer.Option(
        None,
        "--config-path",
        help="Override the location of the login.json file.",
    ),
    base_url: str = typer.Option(
        None,
        "--base-url",
        help="Override the base URL stored in the config (useful for testing).",
    ),
    insecure: bool = typer.Option(
        False,
        "--insecure",
        help="Disable TLS verification when contacting QRM.",
    ),
    output: OutputFormat = typer.Option(
        OutputFormat.rich,
        "--output",
        "-o",
        case_sensitive=False,
        help="Choose output format: rich (default) or json.",
    ),
) -> None:
    """Fetch detailed information about a production box via the `/Box/Get` endpoint.

    Includes all UUTs in the box from the `/Box/Content` endpoint.
    """

    state = load_state_or_exit(config_path)

    client = QrmClient(
        base_url=base_url or str(state.base_url),
        verify_tls=not insecure and state.verify_tls,
    )

    try:
        payload = client.box_get(
            token=state.token,
            box_identifier=box_identifier,
        )
        content = client.box_content(
            token=state.token,
            box_identifier=box_identifier,
        )
    except QrmClientError as exc:
        typer.secho(f"Box get failed: {exc}", fg=typer.colors.RED)
        raise typer.Exit(code=1) from exc

    if output is OutputFormat.json:
        result = {"box": payload, "content": content}
        emit(result, output)
        return

    console.print(render_box_detail(payload))

    # Print UUTs table separately if content exists
    content_list = content if isinstance(content, list) else [content] if content else []
    if content_list:
        uut_table = render_uut_table(content_list)
        console.print(uut_table)


@box_app.command("create")
def box_create(
    box_identifier: str = typer.Argument(..., help="Unique identifier for the production box."),
    started: datetime | None = typer.Option(
        None,
        "--started",
        formats=CLI_DATE_FORMATS,
        help=(
            "When the box manufacturing started (UTC). Accepts ISO-8601 (e.g. 2026-02-01T00:00:00Z) "
            "or YYYY-MM-DD HH:MM:SS."
        ),
    ),
    finished: datetime | None = typer.Option(
        None,
        "--finished",
        formats=CLI_DATE_FORMATS,
        help=(
            "When the box manufacturing finished (UTC). Accepts ISO-8601 (e.g. 2026-02-06T23:59:00Z) "
            "or YYYY-MM-DD HH:MM:SS."
        ),
    ),
    number_of_units: int | None = typer.Option(
        None,
        "--units",
        help="Number of units in the box.",
    ),
    shipped: bool = typer.Option(
        False,
        "--shipped",
        help="Mark the box as shipped.",
    ),
    config_path: Path = typer.Option(
        None,
        "--config-path",
        help="Override the location of the login.json file.",
    ),
    base_url: str = typer.Option(
        None,
        "--base-url",
        help="Override the base URL stored in the config (useful for testing).",
    ),
    insecure: bool = typer.Option(
        False,
        "--insecure",
        help="Disable TLS verification when contacting QRM.",
    ),
    output: OutputFormat = typer.Option(
        OutputFormat.rich,
        "--output",
        "-o",
        case_sensitive=False,
        help="Choose output format: rich (default) or json.",
    ),
) -> None:
    """Create or update a production box via the `/Box/Add` endpoint."""

    state = load_state_or_exit(config_path)

    client = QrmClient(
        base_url=base_url or str(state.base_url),
        verify_tls=not insecure and state.verify_tls,
    )

    try:
        payload = client.box_add(
            token=state.token,
            box_identifier=box_identifier,
            started_datetime=format_api_datetime(started) if started else None,
            finished_datetime=format_api_datetime(finished) if finished else None,
            number_of_units=number_of_units,
            shipped=shipped,
        )
    except QrmClientError as exc:
        typer.secho(f"Box create failed: {exc}", fg=typer.colors.RED)
        raise typer.Exit(code=1) from exc

    emit(payload, output)


@box_app.command("update")
def box_update(
    box_identifier: str = typer.Argument(
        ..., help="Unique identifier for the production box to update."
    ),
    started: datetime | None = typer.Option(
        None,
        "--started",
        formats=CLI_DATE_FORMATS,
        help=(
            "When the box manufacturing started (UTC). Accepts ISO-8601 (e.g. 2026-02-01T00:00:00Z) "
            "or YYYY-MM-DD HH:MM:SS."
        ),
    ),
    finished: datetime | None = typer.Option(
        None,
        "--finished",
        formats=CLI_DATE_FORMATS,
        help=(
            "When the box manufacturing finished (UTC). Accepts ISO-8601 (e.g. 2026-02-06T23:59:00Z) "
            "or YYYY-MM-DD HH:MM:SS."
        ),
    ),
    number_of_units: int | None = typer.Option(
        None,
        "--units",
        help="Number of units in the box.",
    ),
    shipped: bool = typer.Option(
        False,
        "--shipped",
        help="Mark the box as shipped.",
    ),
    config_path: Path = typer.Option(
        None,
        "--config-path",
        help="Override the location of the login.json file.",
    ),
    base_url: str = typer.Option(
        None,
        "--base-url",
        help="Override the base URL stored in the config (useful for testing).",
    ),
    insecure: bool = typer.Option(
        False,
        "--insecure",
        help="Disable TLS verification when contacting QRM.",
    ),
    output: OutputFormat = typer.Option(
        OutputFormat.rich,
        "--output",
        "-o",
        case_sensitive=False,
        help="Choose output format: rich (default) or json.",
    ),
) -> None:
    """Update an existing production box via the `/Box/Add` endpoint."""

    state = load_state_or_exit(config_path)

    client = QrmClient(
        base_url=base_url or str(state.base_url),
        verify_tls=not insecure and state.verify_tls,
    )

    try:
        payload = client.box_add(
            token=state.token,
            box_identifier=box_identifier,
            started_datetime=format_api_datetime(started) if started else None,
            finished_datetime=format_api_datetime(finished) if finished else None,
            number_of_units=number_of_units,
            shipped=shipped,
        )
    except QrmClientError as exc:
        typer.secho(f"Box update failed: {exc}", fg=typer.colors.RED)
        raise typer.Exit(code=1) from exc

    emit(payload, output)


@box_app.command("delete")
def box_delete(
    box_identifier: str = typer.Argument(
        ..., help="Unique identifier for the production box to delete."
    ),
    config_path: Path = typer.Option(
        None,
        "--config-path",
        help="Override the location of the login.json file.",
    ),
    base_url: str = typer.Option(
        None,
        "--base-url",
        help="Override the base URL stored in the config (useful for testing).",
    ),
    insecure: bool = typer.Option(
        False,
        "--insecure",
        help="Disable TLS verification when contacting QRM.",
    ),
    output: OutputFormat = typer.Option(
        OutputFormat.rich,
        "--output",
        "-o",
        case_sensitive=False,
        help="Choose output format: rich (default) or json.",
    ),
) -> None:
    """Delete a production box via the `/Box/Remove` endpoint.

    Idempotent: does not fail if the box is already deleted.
    """

    state = load_state_or_exit(config_path)

    client = QrmClient(
        base_url=base_url or str(state.base_url),
        verify_tls=not insecure and state.verify_tls,
    )

    try:
        payload = client.box_remove(
            token=state.token,
            box_identifier=box_identifier,
        )
    except QrmClientError as exc:
        typer.secho(f"Box delete failed: {exc}", fg=typer.colors.RED)
        raise typer.Exit(code=1) from exc

    emit(payload, output)


@box_app.command("add-item")
def box_add_item(
    box_identifier: str = typer.Argument(..., help="Unique identifier for the production box."),
    uut_serial_number: str | None = typer.Option(
        None,
        "--serial-number",
        help="Serial number of the UUT to add to the box.",
    ),
    uut_type_name: str | None = typer.Option(
        None,
        "--type-name",
        help="Type name of the UUT to add to the box.",
    ),
    identifier_tag: str | None = typer.Option(
        None,
        "--tag",
        help="Identifier tag of the UUT to add to the box.",
    ),
    config_path: Path = typer.Option(
        None,
        "--config-path",
        help="Override the location of the login.json file.",
    ),
    base_url: str = typer.Option(
        None,
        "--base-url",
        help="Override the base URL stored in the config (useful for testing).",
    ),
    insecure: bool = typer.Option(
        False,
        "--insecure",
        help="Disable TLS verification when contacting QRM.",
    ),
    output: OutputFormat = typer.Option(
        OutputFormat.rich,
        "--output",
        "-o",
        case_sensitive=False,
        help="Choose output format: rich (default) or json.",
    ),
) -> None:
    """Add a UUT to a production box via the `/Box/Uut/Add/{boxIdentifier}` endpoint."""

    state = load_state_or_exit(config_path)

    client = QrmClient(
        base_url=base_url or str(state.base_url),
        verify_tls=not insecure and state.verify_tls,
    )

    try:
        payload = client.box_uut_add(
            token=state.token,
            box_identifier=box_identifier,
            uut_serial_number=uut_serial_number,
            uut_type_name=uut_type_name,
            identifier_tag=identifier_tag,
        )
    except QrmClientError as exc:
        typer.secho(f"Box add UUT failed: {exc}", fg=typer.colors.RED)
        raise typer.Exit(code=1) from exc

    emit(payload, output)


@box_app.command("remove-item")
def box_remove_item(
    box_identifier: str = typer.Argument(..., help="Unique identifier for the production box."),
    uut_serial_number: str | None = typer.Option(
        None,
        "--serial-number",
        help="Serial number of the UUT to remove from the box.",
    ),
    uut_type_name: str | None = typer.Option(
        None,
        "--type-name",
        help="Type name of the UUT to remove from the box.",
    ),
    identifier_tag: str | None = typer.Option(
        None,
        "--tag",
        help="Identifier tag of the UUT to remove from the box.",
    ),
    config_path: Path = typer.Option(
        None,
        "--config-path",
        help="Override the location of the login.json file.",
    ),
    base_url: str = typer.Option(
        None,
        "--base-url",
        help="Override the base URL stored in the config (useful for testing).",
    ),
    insecure: bool = typer.Option(
        False,
        "--insecure",
        help="Disable TLS verification when contacting QRM.",
    ),
    output: OutputFormat = typer.Option(
        OutputFormat.rich,
        "--output",
        "-o",
        case_sensitive=False,
        help="Choose output format: rich (default) or json.",
    ),
) -> None:
    """Remove a UUT from a production box via the `/Box/Uut/Remove/{boxIdentifier}` endpoint."""

    state = load_state_or_exit(config_path)

    client = QrmClient(
        base_url=base_url or str(state.base_url),
        verify_tls=not insecure and state.verify_tls,
    )

    try:
        payload = client.box_uut_remove(
            token=state.token,
            box_identifier=box_identifier,
            uut_serial_number=uut_serial_number,
            uut_type_name=uut_type_name,
            identifier_tag=identifier_tag,
        )
    except QrmClientError as exc:
        typer.secho(f"Box remove UUT failed: {exc}", fg=typer.colors.RED)
        raise typer.Exit(code=1) from exc

    emit(payload, output)


@box_app.command("find")
def box_find(
    uut_serial_number: str | None = typer.Option(
        None,
        "--serial-number",
        help="Serial number of the UUT to search for.",
    ),
    uut_type_name: str | None = typer.Option(
        None,
        "--type-name",
        help="Type name of the UUT to search for.",
    ),
    identifier_tag: str | None = typer.Option(
        None,
        "--tag",
        help="Identifier tag of the UUT to search for.",
    ),
    config_path: Path = typer.Option(
        None,
        "--config-path",
        help="Override the location of the login.json file.",
    ),
    base_url: str = typer.Option(
        None,
        "--base-url",
        help="Override the base URL stored in the config (useful for testing).",
    ),
    insecure: bool = typer.Option(
        False,
        "--insecure",
        help="Disable TLS verification when contacting QRM.",
    ),
    output: OutputFormat = typer.Option(
        OutputFormat.rich,
        "--output",
        "-o",
        case_sensitive=False,
        help="Choose output format: rich (default) or json.",
    ),
) -> None:
    """Search for the box containing a UUT via the `/Box/Find` endpoint."""

    state = load_state_or_exit(config_path)

    client = QrmClient(
        base_url=base_url or str(state.base_url),
        verify_tls=not insecure and state.verify_tls,
    )

    try:
        payload = client.box_find(
            token=state.token,
            uut_serial_number=uut_serial_number,
            uut_type_name=uut_type_name,
            identifier_tag=identifier_tag,
        )
    except QrmClientError as exc:
        typer.secho(f"Box find failed: {exc}", fg=typer.colors.RED)
        raise typer.Exit(code=1) from exc

    emit(payload, output)


__all__ = ["box_app"]
