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

assets_app = typer.Typer(help="Patrimonio: maquinas, veiculos e equipamentos.")


def _build_asset_body(
    *,
    name: str,
    asset_type: str,
    manufacturer: Optional[str] = None,
    machine_type: Optional[str] = None,
    is_implement: Optional[bool] = None,
    manufacture_year: Optional[int] = None,
    acquisition_date: Optional[str] = None,
    value: Optional[float] = None,
    currency: Optional[str] = None,
    observations: Optional[str] = None,
    tag_or_model: Optional[str] = None,
    hourmeter: Optional[float] = None,
    odometer: Optional[float] = None,
) -> dict:
    """Build the JSON body for asset creation endpoints."""
    body: dict = {
        "name": name,
        "type": asset_type,
    }
    if manufacturer is not None:
        body["manufacturer"] = manufacturer
    if machine_type is not None:
        body["machineType"] = machine_type
    if is_implement is not None:
        body["isImplement"] = is_implement
    if manufacture_year is not None:
        body["manufactureYear"] = manufacture_year
    if acquisition_date is not None:
        body["acquisitionDate"] = acquisition_date
    if value is not None:
        body["value"] = {
            "currencyCode": currency or "BRL",
            "amount": value,
        }
    if observations is not None:
        body["observations"] = observations
    if tag_or_model is not None:
        body["tagOrModel"] = tag_or_model
    if hourmeter is not None:
        body["currentHourmeter"] = hourmeter
    if odometer is not None:
        body["currentOdometer"] = odometer
    return body


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

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


@assets_app.command("list")
def list_assets(
    type_filter: Optional[list[str]] = typer.Option(
        None, "--type", help="Tipo do patrimonio (repetivel)."
    ),
    machine_type: Optional[list[str]] = typer.Option(
        None, "--machine-type", help="Tipo de maquina (repetivel)."
    ),
    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 patrimonios da fazenda ativa com filtros opcionais.

    EXAMPLES:
      aegro assets list
      aegro assets list --type MACHINE --type VEHICLE
      aegro assets list --machine-type TRACTOR --page 2 --output table
    """
    try:
        _, api_key = require_farm()
        client = get_client()
        body: dict = {
            "requiredPageNumber": page,
            "maximumItemsPerPageCount": 50,
        }
        if type_filter:
            body["types"] = type_filter
        if machine_type:
            body["machineTypes"] = machine_type
        result = client.post("/pub/v1/assets/filter", api_key=api_key, json_body=body)
        if result is None:
            typer.echo("Nenhum patrimonio encontrado.")
            return
        typer.echo(format_output(result, output))
    except (SystemExit, KeyboardInterrupt):
        raise
    except Exception as exc:
        handle_error(exc)


@assets_app.command("create-machine")
def create_machine(
    name: str = typer.Option(..., "--name", "-n", help="Nome da maquina."),
    manufacturer: Optional[str] = typer.Option(None, "--manufacturer", "-m", help="Fabricante."),
    machine_type: Optional[str] = typer.Option(None, "--machine-type", help="Tipo de maquina."),
    is_implement: bool = typer.Option(False, "--is-implement", help="E um implemento?"),
    manufacture_year: Optional[int] = typer.Option(
        None, "--manufacture-year", help="Ano de fabricacao."
    ),
    acquisition_date: Optional[str] = typer.Option(
        None, "--acquisition-date", help="Data de aquisicao (YYYY-MM-DD)."
    ),
    value: Optional[float] = typer.Option(None, "--value", help="Valor do patrimonio."),
    currency: Optional[str] = typer.Option(None, "--currency", help="Codigo da moeda (ex: BRL)."),
    observations: Optional[str] = typer.Option(None, "--observations", help="Observacoes."),
    tag_or_model: Optional[str] = typer.Option(None, "--tag-or-model", help="Tag ou modelo."),
    hourmeter: Optional[float] = typer.Option(None, "--hourmeter", help="Horimetro atual."),
    output: OutputFormat = typer.Option(
        OutputFormat.json, "--output", "-o", help="Formato: json|table|csv"
    ),
) -> None:
    """Cria uma nova maquina.

    EXAMPLES:
      aegro assets create-machine --name "Trator John Deere" --manufacturer "John Deere"
    """
    try:
        _, api_key = require_farm()
        client = get_client()
        body = _build_asset_body(
            name=name,
            asset_type="MACHINE",
            manufacturer=manufacturer,
            machine_type=machine_type,
            is_implement=is_implement,
            manufacture_year=manufacture_year,
            acquisition_date=acquisition_date,
            value=value,
            currency=currency,
            observations=observations,
            tag_or_model=tag_or_model,
            hourmeter=hourmeter,
        )
        result = client.post("/pub/v1/assets/machines", api_key=api_key, json_body=body)
        if result is None:
            typer.echo("Erro ao criar maquina.")
            return
        typer.echo(format_output(result, output))
    except (SystemExit, KeyboardInterrupt):
        raise
    except Exception as exc:
        handle_error(exc)


@assets_app.command("create-vehicle")
def create_vehicle(
    name: str = typer.Option(..., "--name", "-n", help="Nome do veiculo."),
    manufacturer: Optional[str] = typer.Option(None, "--manufacturer", "-m", help="Fabricante."),
    manufacture_year: Optional[int] = typer.Option(
        None, "--manufacture-year", help="Ano de fabricacao."
    ),
    acquisition_date: Optional[str] = typer.Option(
        None, "--acquisition-date", help="Data de aquisicao (YYYY-MM-DD)."
    ),
    value: Optional[float] = typer.Option(None, "--value", help="Valor do patrimonio."),
    currency: Optional[str] = typer.Option(None, "--currency", help="Codigo da moeda (ex: BRL)."),
    observations: Optional[str] = typer.Option(None, "--observations", help="Observacoes."),
    tag_or_model: Optional[str] = typer.Option(None, "--tag-or-model", help="Tag ou modelo."),
    odometer: Optional[float] = typer.Option(None, "--odometer", help="Hodometro atual."),
    output: OutputFormat = typer.Option(
        OutputFormat.json, "--output", "-o", help="Formato: json|table|csv"
    ),
) -> None:
    """Cria um novo veiculo.

    EXAMPLES:
      aegro assets create-vehicle --name "Caminhonete Toyota" --manufacturer "Toyota"
    """
    try:
        _, api_key = require_farm()
        client = get_client()
        body = _build_asset_body(
            name=name,
            asset_type="VEHICLE",
            manufacturer=manufacturer,
            manufacture_year=manufacture_year,
            acquisition_date=acquisition_date,
            value=value,
            currency=currency,
            observations=observations,
            tag_or_model=tag_or_model,
            odometer=odometer,
        )
        result = client.post("/pub/v1/assets/vehicles", api_key=api_key, json_body=body)
        if result is None:
            typer.echo("Erro ao criar veiculo.")
            return
        typer.echo(format_output(result, output))
    except (SystemExit, KeyboardInterrupt):
        raise
    except Exception as exc:
        handle_error(exc)


@assets_app.command("create-garner")
def create_garner(
    name: str = typer.Option(..., "--name", "-n", help="Nome do graneleiro."),
    manufacturer: Optional[str] = typer.Option(None, "--manufacturer", "-m", help="Fabricante."),
    manufacture_year: Optional[int] = typer.Option(
        None, "--manufacture-year", help="Ano de fabricacao."
    ),
    acquisition_date: Optional[str] = typer.Option(
        None, "--acquisition-date", help="Data de aquisicao (YYYY-MM-DD)."
    ),
    value: Optional[float] = typer.Option(None, "--value", help="Valor do patrimonio."),
    currency: Optional[str] = typer.Option(None, "--currency", help="Codigo da moeda (ex: BRL)."),
    observations: Optional[str] = typer.Option(None, "--observations", help="Observacoes."),
    tag_or_model: Optional[str] = typer.Option(None, "--tag-or-model", help="Tag ou modelo."),
    hourmeter: Optional[float] = typer.Option(None, "--hourmeter", help="Horimetro atual."),
    output: OutputFormat = typer.Option(
        OutputFormat.json, "--output", "-o", help="Formato: json|table|csv"
    ),
) -> None:
    """Cria um novo graneleiro.

    EXAMPLES:
      aegro assets create-garner --name "Graneleiro 1" --manufacturer "Stara"
    """
    try:
        _, api_key = require_farm()
        client = get_client()
        body = _build_asset_body(
            name=name,
            asset_type="GARNER",
            manufacturer=manufacturer,
            manufacture_year=manufacture_year,
            acquisition_date=acquisition_date,
            value=value,
            currency=currency,
            observations=observations,
            tag_or_model=tag_or_model,
            hourmeter=hourmeter,
        )
        result = client.post("/pub/v1/assets/garners", api_key=api_key, json_body=body)
        if result is None:
            typer.echo("Erro ao criar graneleiro.")
            return
        typer.echo(format_output(result, output))
    except (SystemExit, KeyboardInterrupt):
        raise
    except Exception as exc:
        handle_error(exc)


@assets_app.command("create-immobilized")
def create_immobilized(
    name: str = typer.Option(..., "--name", "-n", help="Nome do imobilizado."),
    manufacturer: Optional[str] = typer.Option(None, "--manufacturer", "-m", help="Fabricante."),
    is_implement: bool = typer.Option(False, "--is-implement", help="E um implemento?"),
    manufacture_year: Optional[int] = typer.Option(
        None, "--manufacture-year", help="Ano de fabricacao."
    ),
    acquisition_date: Optional[str] = typer.Option(
        None, "--acquisition-date", help="Data de aquisicao (YYYY-MM-DD)."
    ),
    value: Optional[float] = typer.Option(None, "--value", help="Valor do patrimonio."),
    currency: Optional[str] = typer.Option(None, "--currency", help="Codigo da moeda (ex: BRL)."),
    observations: Optional[str] = typer.Option(None, "--observations", help="Observacoes."),
    tag_or_model: Optional[str] = typer.Option(None, "--tag-or-model", help="Tag ou modelo."),
    output: OutputFormat = typer.Option(
        OutputFormat.json, "--output", "-o", help="Formato: json|table|csv"
    ),
) -> None:
    """Cria um novo imobilizado.

    EXAMPLES:
      aegro assets create-immobilized --name "Silo 1" --manufacturer "Kepler Weber"
    """
    try:
        _, api_key = require_farm()
        client = get_client()
        body = _build_asset_body(
            name=name,
            asset_type="IMMOBILIZED",
            manufacturer=manufacturer,
            is_implement=is_implement,
            manufacture_year=manufacture_year,
            acquisition_date=acquisition_date,
            value=value,
            currency=currency,
            observations=observations,
            tag_or_model=tag_or_model,
        )
        result = client.post("/pub/v1/assets/immobilizeds", api_key=api_key, json_body=body)
        if result is None:
            typer.echo("Erro ao criar imobilizado.")
            return
        typer.echo(format_output(result, output))
    except (SystemExit, KeyboardInterrupt):
        raise
    except Exception as exc:
        handle_error(exc)


@assets_app.command("create-pivot")
def create_pivot(
    name: str = typer.Option(..., "--name", "-n", help="Nome do pivo."),
    manufacturer: Optional[str] = typer.Option(None, "--manufacturer", "-m", help="Fabricante."),
    manufacture_year: Optional[int] = typer.Option(
        None, "--manufacture-year", help="Ano de fabricacao."
    ),
    acquisition_date: Optional[str] = typer.Option(
        None, "--acquisition-date", help="Data de aquisicao (YYYY-MM-DD)."
    ),
    value: Optional[float] = typer.Option(None, "--value", help="Valor do patrimonio."),
    currency: Optional[str] = typer.Option(None, "--currency", help="Codigo da moeda (ex: BRL)."),
    observations: Optional[str] = typer.Option(None, "--observations", help="Observacoes."),
    tag_or_model: Optional[str] = typer.Option(None, "--tag-or-model", help="Tag ou modelo."),
    hourmeter: Optional[float] = typer.Option(None, "--hourmeter", help="Horimetro atual."),
    output: OutputFormat = typer.Option(
        OutputFormat.json, "--output", "-o", help="Formato: json|table|csv"
    ),
) -> None:
    """Cria um novo pivo de irrigacao.

    EXAMPLES:
      aegro assets create-pivot --name "Pivo Central" --manufacturer "Valley"
    """
    try:
        _, api_key = require_farm()
        client = get_client()
        body = _build_asset_body(
            name=name,
            asset_type="PIVOT",
            manufacturer=manufacturer,
            manufacture_year=manufacture_year,
            acquisition_date=acquisition_date,
            value=value,
            currency=currency,
            observations=observations,
            tag_or_model=tag_or_model,
            hourmeter=hourmeter,
        )
        result = client.post("/pub/v1/assets/pivots", api_key=api_key, json_body=body)
        if result is None:
            typer.echo("Erro ao criar pivo.")
            return
        typer.echo(format_output(result, output))
    except (SystemExit, KeyboardInterrupt):
        raise
    except Exception as exc:
        handle_error(exc)


@assets_app.command("create-weather-station")
def create_weather_station(
    name: str = typer.Option(..., "--name", "-n", help="Nome da estacao meteorologica."),
    manufacturer: Optional[str] = typer.Option(None, "--manufacturer", "-m", help="Fabricante."),
    manufacture_year: Optional[int] = typer.Option(
        None, "--manufacture-year", help="Ano de fabricacao."
    ),
    acquisition_date: Optional[str] = typer.Option(
        None, "--acquisition-date", help="Data de aquisicao (YYYY-MM-DD)."
    ),
    value: Optional[float] = typer.Option(None, "--value", help="Valor do patrimonio."),
    currency: Optional[str] = typer.Option(None, "--currency", help="Codigo da moeda (ex: BRL)."),
    observations: Optional[str] = typer.Option(None, "--observations", help="Observacoes."),
    tag_or_model: Optional[str] = typer.Option(None, "--tag-or-model", help="Tag ou modelo."),
    hourmeter: Optional[float] = typer.Option(None, "--hourmeter", help="Horimetro atual."),
    output: OutputFormat = typer.Option(
        OutputFormat.json, "--output", "-o", help="Formato: json|table|csv"
    ),
) -> None:
    """Cria uma nova estacao meteorologica.

    EXAMPLES:
      aegro assets create-weather-station --name "Estacao Norte" --manufacturer "Davis"
    """
    try:
        _, api_key = require_farm()
        client = get_client()
        body = _build_asset_body(
            name=name,
            asset_type="WEATHER_STATION",
            manufacturer=manufacturer,
            manufacture_year=manufacture_year,
            acquisition_date=acquisition_date,
            value=value,
            currency=currency,
            observations=observations,
            tag_or_model=tag_or_model,
            hourmeter=hourmeter,
        )
        result = client.post("/pub/v1/assets/weather-stations", api_key=api_key, json_body=body)
        if result is None:
            typer.echo("Erro ao criar estacao meteorologica.")
            return
        typer.echo(format_output(result, output))
    except (SystemExit, KeyboardInterrupt):
        raise
    except Exception as exc:
        handle_error(exc)
