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

elements_app = typer.Typer(help="Insumos e elementos (defensivos, fertilizantes, sementes, etc).")


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

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


@elements_app.command("list")
def list_elements(
    category: Optional[list[str]] = typer.Option(
        None, "--category", help="Categoria do elemento (repetivel para multiplas)."
    ),
    type_filter: Optional[list[str]] = typer.Option(
        None, "--type", help="Tipo do elemento (repetivel para multiplos)."
    ),
    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 elementos com filtros opcionais de categoria e tipo.

    EXAMPLES:
      aegro elements list
      aegro elements list --category DEFENSIVE --category FERTILIZER
      aegro elements list --type HERBICIDE --page 2
    """
    try:
        _, api_key = require_farm()
        client = get_client()
        body: dict = {
            "requiredPageNumber": page,
            "maximumItemsPerPageCount": 50,
        }
        if category:
            body["categories"] = category
        if type_filter:
            body["types"] = type_filter
        result = client.post("/pub/v1/elements/filter", api_key=api_key, json_body=body)
        if result is None:
            typer.echo("Nenhum elemento encontrado.")
            return
        typer.echo(format_output(result, output))
    except (SystemExit, KeyboardInterrupt):
        raise
    except Exception as exc:
        handle_error(exc)


@elements_app.command("create-defensive")
def create_defensive(
    name: str = typer.Option(..., "--name", help="Nome do defensivo."),
    type_value: str = typer.Option(..., "--type", help="Tipo do defensivo."),
    unit: str = typer.Option(..., "--unit", help="Unidade de medida."),
    manufacturer: Optional[str] = typer.Option(None, "--manufacturer", help="Fabricante."),
    observations: Optional[str] = typer.Option(None, "--observations", help="Observacoes."),
    output: OutputFormat = typer.Option(
        OutputFormat.json, "--output", "-o", help="Formato: json|table|csv"
    ),
) -> None:
    """Cria um novo defensivo.

    EXAMPLES:
      aegro elements create-defensive --name "Roundup" --type HERBICIDE --unit L
      aegro elements create-defensive --name "Engeo" --type INSECTICIDE --unit L --manufacturer Syngenta
    """
    try:
        _, api_key = require_farm()
        client = get_client()
        body: dict = {
            "name": name,
            "type": type_value,
            "measuringUnit": unit,
        }
        if manufacturer is not None:
            body["manufacturer"] = manufacturer
        if observations is not None:
            body["observations"] = observations
        result = client.post("/pub/v1/elements/defensives", api_key=api_key, json_body=body)
        if result is None:
            typer.echo("Erro ao criar defensivo.")
            return
        typer.echo(format_output(result, output))
    except (SystemExit, KeyboardInterrupt):
        raise
    except Exception as exc:
        handle_error(exc)


@elements_app.command("create-fertilizer")
def create_fertilizer(
    name: str = typer.Option(..., "--name", help="Nome do fertilizante."),
    unit: str = typer.Option(..., "--unit", help="Unidade de medida."),
    manufacturer: Optional[str] = typer.Option(None, "--manufacturer", help="Fabricante."),
    observations: Optional[str] = typer.Option(None, "--observations", help="Observacoes."),
    output: OutputFormat = typer.Option(
        OutputFormat.json, "--output", "-o", help="Formato: json|table|csv"
    ),
) -> None:
    """Cria um novo fertilizante.

    EXAMPLES:
      aegro elements create-fertilizer --name "Ureia" --unit KG
      aegro elements create-fertilizer --name "MAP" --unit KG --manufacturer Mosaic
    """
    try:
        _, api_key = require_farm()
        client = get_client()
        body: dict = {
            "name": name,
            "measuringUnit": unit,
        }
        if manufacturer is not None:
            body["manufacturer"] = manufacturer
        if observations is not None:
            body["observations"] = observations
        result = client.post("/pub/v1/elements/fertilizers", api_key=api_key, json_body=body)
        if result is None:
            typer.echo("Erro ao criar fertilizante.")
            return
        typer.echo(format_output(result, output))
    except (SystemExit, KeyboardInterrupt):
        raise
    except Exception as exc:
        handle_error(exc)


@elements_app.command("create-item")
def create_item(
    name: str = typer.Option(..., "--name", help="Nome do item."),
    type_value: str = typer.Option(..., "--type", help="Tipo do item."),
    unit: str = typer.Option(..., "--unit", help="Unidade de medida."),
    manufacturer: Optional[str] = typer.Option(None, "--manufacturer", help="Fabricante."),
    observations: Optional[str] = typer.Option(None, "--observations", help="Observacoes."),
    output: OutputFormat = typer.Option(
        OutputFormat.json, "--output", "-o", help="Formato: json|table|csv"
    ),
) -> None:
    """Cria um novo item.

    EXAMPLES:
      aegro elements create-item --name "Parafuso" --type GENERAL --unit UN
    """
    try:
        _, api_key = require_farm()
        client = get_client()
        body: dict = {
            "name": name,
            "type": type_value,
            "measuringUnit": unit,
        }
        if manufacturer is not None:
            body["manufacturer"] = manufacturer
        if observations is not None:
            body["observations"] = observations
        result = client.post("/pub/v1/elements/items", api_key=api_key, json_body=body)
        if result is None:
            typer.echo("Erro ao criar item.")
            return
        typer.echo(format_output(result, output))
    except (SystemExit, KeyboardInterrupt):
        raise
    except Exception as exc:
        handle_error(exc)


@elements_app.command("create-seed")
def create_seed(
    name: str = typer.Option(..., "--name", help="Nome da semente."),
    type_value: str = typer.Option(..., "--type", help="Tipo da semente."),
    unit: str = typer.Option(..., "--unit", help="Unidade de medida."),
    manufacturer: Optional[str] = typer.Option(None, "--manufacturer", help="Fabricante."),
    observations: Optional[str] = typer.Option(None, "--observations", help="Observacoes."),
    output: OutputFormat = typer.Option(
        OutputFormat.json, "--output", "-o", help="Formato: json|table|csv"
    ),
) -> None:
    """Cria uma nova semente.

    EXAMPLES:
      aegro elements create-seed --name "TMG 2381" --type SOYBEAN --unit KG
    """
    try:
        _, api_key = require_farm()
        client = get_client()
        body: dict = {
            "name": name,
            "type": type_value,
            "measuringUnit": unit,
        }
        if manufacturer is not None:
            body["manufacturer"] = manufacturer
        if observations is not None:
            body["observations"] = observations
        result = client.post("/pub/v1/elements/seeds", api_key=api_key, json_body=body)
        if result is None:
            typer.echo("Erro ao criar semente.")
            return
        typer.echo(format_output(result, output))
    except (SystemExit, KeyboardInterrupt):
        raise
    except Exception as exc:
        handle_error(exc)


@elements_app.command("create-service")
def create_service(
    name: str = typer.Option(..., "--name", help="Nome do servico."),
    unit: str = typer.Option(..., "--unit", help="Unidade de medida."),
    output: OutputFormat = typer.Option(
        OutputFormat.json, "--output", "-o", help="Formato: json|table|csv"
    ),
) -> None:
    """Cria um novo servico.

    EXAMPLES:
      aegro elements create-service --name "Pulverizacao" --unit HA
    """
    try:
        _, api_key = require_farm()
        client = get_client()
        body: dict = {
            "name": name,
            "measuringUnit": unit,
        }
        result = client.post("/pub/v1/elements/services", api_key=api_key, json_body=body)
        if result is None:
            typer.echo("Erro ao criar servico.")
            return
        typer.echo(format_output(result, output))
    except (SystemExit, KeyboardInterrupt):
        raise
    except Exception as exc:
        handle_error(exc)


@elements_app.command("set-categories")
def set_categories(
    element_key: str = typer.Argument(help="Chave unica do elemento."),
    revenue_category_key: Optional[str] = typer.Option(
        None, "--revenue-category-key", help="Chave da categoria financeira de receita."
    ),
    expense_category_key: Optional[str] = typer.Option(
        None, "--expense-category-key", help="Chave da categoria financeira de despesa."
    ),
    output: OutputFormat = typer.Option(
        OutputFormat.json, "--output", "-o", help="Formato: json|table|csv"
    ),
) -> None:
    """Associa categorias financeiras a um elemento.

    EXAMPLES:
      aegro elements set-categories elem-1 --revenue-category-key rev-1 --expense-category-key exp-1
      aegro elements set-categories elem-1 --expense-category-key exp-1
    """
    try:
        _, api_key = require_farm()
        client = get_client()
        associations: dict = {}
        if revenue_category_key is not None:
            associations["revenueFinancialCategory"] = {"key": revenue_category_key}
        if expense_category_key is not None:
            associations["expenseFinancialCategory"] = {"key": expense_category_key}
        body: dict = {"associations": associations}
        result = client.post(
            f"/pub/v1/elements/{validate_key(element_key)}/financial-categories",
            api_key=api_key,
            json_body=body,
        )
        if result is None:
            typer.echo("Erro ao associar categorias financeiras.")
            return
        typer.echo(format_output(result, output))
    except (SystemExit, KeyboardInterrupt):
        raise
    except Exception as exc:
        handle_error(exc)
