from __future__ import annotations

from typing import Optional

import typer

from aegro.cli._config import get_client, require_farm
from aegro.cli._errors import handle_error
from aegro.cli._output import OutputFormat, format_output
from aegro.validation import validate_key

stock_app = typer.Typer(help="Estoque: itens, locais, movimentacoes.")


@stock_app.command("item")
def get_item(
    key: str = typer.Argument(help="Chave unica do item de estoque."),
    output: OutputFormat = typer.Option(
        OutputFormat.json, "--output", "-o", help="Formato: json|table|csv"
    ),
) -> None:
    """Retorna os dados de um item de estoque pelo identificador.

    EXAMPLES:
      aegro stock item abc123
      aegro stock item abc123 --output table
    """
    try:
        _, api_key = require_farm()
        client = get_client()
        result = client.get(f"/pub/v1/stock-items/{validate_key(key)}", api_key=api_key)
        if result is None:
            typer.echo("Item de estoque nao encontrado.")
            return
        typer.echo(format_output(result, output))
    except (SystemExit, KeyboardInterrupt):
        raise
    except Exception as exc:
        handle_error(exc)


@stock_app.command("location")
def get_location(
    key: str = typer.Argument(help="Chave unica do local de estoque."),
    output: OutputFormat = typer.Option(
        OutputFormat.json, "--output", "-o", help="Formato: json|table|csv"
    ),
) -> None:
    """Retorna os dados de um local de estoque pelo identificador.

    EXAMPLES:
      aegro stock location abc123
    """
    try:
        _, api_key = require_farm()
        client = get_client()
        result = client.get(f"/pub/v1/stock-locations/{validate_key(key)}", api_key=api_key)
        if result is None:
            typer.echo("Local de estoque nao encontrado.")
            return
        typer.echo(format_output(result, output))
    except (SystemExit, KeyboardInterrupt):
        raise
    except Exception as exc:
        handle_error(exc)


@stock_app.command("items")
def list_items(
    location_key: Optional[str] = typer.Option(
        None, "--location-key", help="Chave do local de estoque."
    ),
    element_key: Optional[str] = typer.Option(
        None, "--element-key", help="Chave do insumo/elemento."
    ),
    crop_key: Optional[str] = typer.Option(None, "--crop-key", help="Chave da safra."),
    page: int = typer.Option(1, "--page", help="Numero da pagina."),
    output: OutputFormat = typer.Option(
        OutputFormat.json, "--output", "-o", help="Formato: json|table|csv"
    ),
) -> None:
    """Lista itens de estoque com filtros opcionais.

    EXAMPLES:
      aegro stock items
      aegro stock items --location-key loc1 --element-key elem1
      aegro stock items --crop-key crop1 --page 2
    """
    try:
        _, api_key = require_farm()
        client = get_client()
        body: dict = {
            "requiredPageNumber": page,
            "maximumItemsPerPageCount": 50,
        }
        if location_key is not None:
            body["locationKey"] = location_key
        if element_key is not None:
            body["elementKey"] = element_key
        if crop_key is not None:
            body["cropKey"] = crop_key
        result = client.post("/pub/v1/stock-items/filter", api_key=api_key, json_body=body)
        if result is None:
            typer.echo("Nenhum item de estoque encontrado.")
            return
        typer.echo(format_output(result, output))
    except (SystemExit, KeyboardInterrupt):
        raise
    except Exception as exc:
        handle_error(exc)


@stock_app.command("locations")
def list_locations(
    page: int = typer.Option(1, "--page", help="Numero da pagina."),
    output: OutputFormat = typer.Option(
        OutputFormat.json, "--output", "-o", help="Formato: json|table|csv"
    ),
) -> None:
    """Lista locais de estoque.

    EXAMPLES:
      aegro stock locations
      aegro stock locations --page 2 --output table
    """
    try:
        _, api_key = require_farm()
        client = get_client()
        body: dict = {
            "requiredPageNumber": page,
            "maximumItemsPerPageCount": 50,
        }
        result = client.post("/pub/v1/stock-locations/filter", api_key=api_key, json_body=body)
        if result is None:
            typer.echo("Nenhum local de estoque encontrado.")
            return
        typer.echo(format_output(result, output))
    except (SystemExit, KeyboardInterrupt):
        raise
    except Exception as exc:
        handle_error(exc)


@stock_app.command("logs")
def list_logs(
    element_key: Optional[str] = typer.Option(
        None, "--element-key", help="Chave do insumo/elemento."
    ),
    start_date: Optional[str] = typer.Option(
        None, "--start-date", help="Data inicial (YYYY-MM-DD)."
    ),
    end_date: Optional[str] = typer.Option(None, "--end-date", help="Data final (YYYY-MM-DD)."),
    source_key: Optional[str] = typer.Option(
        None, "--source-key", help="Chave do local de origem."
    ),
    dest_key: Optional[str] = typer.Option(None, "--dest-key", help="Chave do local de destino."),
    page: int = typer.Option(1, "--page", help="Numero da pagina."),
    output: OutputFormat = typer.Option(
        OutputFormat.json, "--output", "-o", help="Formato: json|table|csv"
    ),
) -> None:
    """Lista movimentacoes de estoque com filtros opcionais.

    EXAMPLES:
      aegro stock logs
      aegro stock logs --element-key elem1 --start-date 2025-01-01
      aegro stock logs --source-key loc1 --dest-key loc2
    """
    try:
        _, api_key = require_farm()
        client = get_client()
        body: dict = {
            "requiredPageNumber": page,
            "maximumItemsPerPageCount": 50,
        }
        if element_key is not None:
            body["elementKey"] = element_key
        if start_date is not None:
            body["startDate"] = start_date
        if end_date is not None:
            body["endDate"] = end_date
        if source_key is not None:
            body["sourceLocationKey"] = source_key
        if dest_key is not None:
            body["destinationLocationKey"] = dest_key
        result = client.post("/pub/v1/stock-logs/filter", api_key=api_key, json_body=body)
        if result is None:
            typer.echo("Nenhuma movimentacao de estoque encontrada.")
            return
        typer.echo(format_output(result, output))
    except (SystemExit, KeyboardInterrupt):
        raise
    except Exception as exc:
        handle_error(exc)


@stock_app.command("log")
def get_log(
    key: str = typer.Argument(help="Chave unica da movimentacao de estoque."),
    output: OutputFormat = typer.Option(
        OutputFormat.json, "--output", "-o", help="Formato: json|table|csv"
    ),
) -> None:
    """Retorna os dados de uma movimentacao de estoque pelo identificador.

    EXAMPLES:
      aegro stock log abc123
    """
    try:
        _, api_key = require_farm()
        client = get_client()
        result = client.get(f"/pub/v1/stock-logs/{validate_key(key)}", api_key=api_key)
        if result is None:
            typer.echo("Movimentacao de estoque nao encontrada.")
            return
        typer.echo(format_output(result, output))
    except (SystemExit, KeyboardInterrupt):
        raise
    except Exception as exc:
        handle_error(exc)


@stock_app.command("transfer")
def transfer(
    element_key: str = typer.Option(..., "--element-key", help="Chave do insumo/elemento."),
    quantity: float = typer.Option(..., "--quantity", help="Quantidade a transferir."),
    unit: str = typer.Option(..., "--unit", help="Unidade de medida (ex: kg, L, un)."),
    date: str = typer.Option(..., "--date", help="Data da ocorrencia (YYYY-MM-DD)."),
    source_key: str = typer.Option(..., "--source-key", help="Chave do local de origem."),
    dest_key: str = typer.Option(..., "--dest-key", help="Chave do local de destino."),
    observations: Optional[str] = typer.Option(
        None, "--observations", help="Observacoes opcionais."
    ),
    output: OutputFormat = typer.Option(
        OutputFormat.json, "--output", "-o", help="Formato: json|table|csv"
    ),
) -> None:
    """Transfere estoque entre locais.

    EXAMPLES:
      aegro stock transfer --element-key e1 --quantity 100 --unit kg \\
        --date 2025-06-01 --source-key loc1 --dest-key loc2
    """
    try:
        farm_name, api_key = require_farm()
        client = get_client()
        body: dict = {
            "elementKey": element_key,
            "quantity": {"magnitude": quantity, "unit": unit},
            "occurrenceDate": date,
            "sourceLocationKey": source_key,
            "destinationLocationKey": dest_key,
        }
        if observations is not None:
            body["observations"] = observations
        result = client.post("/pub/v1/stock-logs", api_key=api_key, json_body=body)
        if result is None:
            typer.echo(f"Transferencia criada na fazenda '{farm_name}'.")
        else:
            typer.echo(format_output(result, output))
    except (SystemExit, KeyboardInterrupt):
        raise
    except Exception as exc:
        handle_error(exc)


@stock_app.command("entry")
def entry(
    element_key: str = typer.Option(..., "--element-key", help="Chave do insumo/elemento."),
    quantity: float = typer.Option(..., "--quantity", help="Quantidade a adicionar."),
    unit: str = typer.Option(..., "--unit", help="Unidade de medida (ex: kg, L, un)."),
    date: str = typer.Option(..., "--date", help="Data da ocorrencia (YYYY-MM-DD)."),
    amount: float = typer.Option(..., "--amount", help="Valor monetario."),
    currency: str = typer.Option("BRL", "--currency", help="Codigo da moeda (default: BRL)."),
    dest_key: str = typer.Option(..., "--dest-key", help="Chave do local de destino."),
    observations: Optional[str] = typer.Option(
        None, "--observations", help="Observacoes opcionais."
    ),
    output: OutputFormat = typer.Option(
        OutputFormat.json, "--output", "-o", help="Formato: json|table|csv"
    ),
) -> None:
    """Registra uma entrada manual de estoque.

    EXAMPLES:
      aegro stock entry --element-key e1 --quantity 50 --unit kg \\
        --date 2025-06-01 --amount 500.00 --dest-key loc1
    """
    try:
        farm_name, api_key = require_farm()
        client = get_client()
        body: dict = {
            "elementKey": element_key,
            "quantity": {"magnitude": quantity, "unit": unit},
            "occurrenceDate": date,
            "amount": {"amount": amount, "currencyCode": currency},
            "destinationLocationKey": dest_key,
        }
        if observations is not None:
            body["observations"] = observations
        result = client.post("/pub/v1/stock-logs/manual-entries", api_key=api_key, json_body=body)
        if result is None:
            typer.echo(f"Entrada de estoque criada na fazenda '{farm_name}'.")
        else:
            typer.echo(format_output(result, output))
    except (SystemExit, KeyboardInterrupt):
        raise
    except Exception as exc:
        handle_error(exc)


@stock_app.command("removal")
def removal(
    element_key: str = typer.Option(..., "--element-key", help="Chave do insumo/elemento."),
    quantity: float = typer.Option(..., "--quantity", help="Quantidade a remover."),
    unit: str = typer.Option(..., "--unit", help="Unidade de medida (ex: kg, L, un)."),
    date: str = typer.Option(..., "--date", help="Data da ocorrencia (YYYY-MM-DD)."),
    source_key: str = typer.Option(..., "--source-key", help="Chave do local de origem."),
    observations: Optional[str] = typer.Option(
        None, "--observations", help="Observacoes opcionais."
    ),
    output: OutputFormat = typer.Option(
        OutputFormat.json, "--output", "-o", help="Formato: json|table|csv"
    ),
) -> None:
    """Registra uma remocao manual de estoque.

    EXAMPLES:
      aegro stock removal --element-key e1 --quantity 10 --unit kg \\
        --date 2025-06-01 --source-key loc1
    """
    try:
        farm_name, api_key = require_farm()
        client = get_client()
        body: dict = {
            "elementKey": element_key,
            "quantity": {"magnitude": quantity, "unit": unit},
            "occurrenceDate": date,
            "sourceLocationKey": source_key,
        }
        if observations is not None:
            body["observations"] = observations
        result = client.post("/pub/v1/stock-logs/manual-removals", api_key=api_key, json_body=body)
        if result is None:
            typer.echo(f"Remocao de estoque criada na fazenda '{farm_name}'.")
        else:
            typer.echo(format_output(result, output))
    except (SystemExit, KeyboardInterrupt):
        raise
    except Exception as exc:
        handle_error(exc)
