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

fin_categories_app = typer.Typer(help="Categorias financeiras.")


@fin_categories_app.command("get")
def get_financial_category(
    key: str = typer.Argument(help="Chave unica da categoria financeira."),
    output: OutputFormat = typer.Option(
        OutputFormat.json, "--output", "-o", help="Formato: json|table|csv"
    ),
) -> None:
    """Retorna os dados de uma categoria financeira pelo seu identificador.

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


@fin_categories_app.command("list")
def list_financial_categories(
    cat_type: Optional[list[str]] = typer.Option(
        None, "--type", help="Tipo da categoria (repetivel)."
    ),
    operation_type: Optional[list[str]] = typer.Option(
        None, "--operation-type", help="Tipo de operacao (repetivel)."
    ),
    status: Optional[list[str]] = typer.Option(
        None, "--status", help="Status da categoria (repetivel)."
    ),
    search_text: Optional[str] = typer.Option(None, "--search-text", help="Texto de busca."),
    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 categorias financeiras com filtros opcionais.

    EXAMPLES:
      aegro fin-categories list
      aegro fin-categories list --type EXPENSE --operation-type DEBIT --status ACTIVE
      aegro fin-categories list --search-text "Insumos" --page 2
    """
    try:
        _, api_key = require_farm()
        client = get_client()
        body: dict = {
            "requiredPageNumber": page,
            "maximumItemsPerPageCount": 50,
        }
        if cat_type:
            body["types"] = cat_type
        if operation_type:
            body["operationTypes"] = operation_type
        if status:
            body["statuses"] = status
        if search_text is not None:
            body["searchText"] = search_text
        result = client.post("/pub/v1/financial-categories/filter", api_key=api_key, json_body=body)
        if result is None:
            typer.echo("Nenhuma categoria financeira encontrada.")
            return
        typer.echo(format_output(result, output))
    except (SystemExit, KeyboardInterrupt):
        raise
    except Exception as exc:
        handle_error(exc)


@fin_categories_app.command("create")
def create_financial_category(
    description: str = typer.Option(..., "--description", help="Descricao da categoria."),
    cat_type: str = typer.Option(..., "--type", help="Tipo da categoria."),
    operation_type: str = typer.Option(..., "--operation-type", help="Tipo de operacao."),
    status: str = typer.Option(..., "--status", help="Status da categoria."),
    bill_type: str = typer.Option(..., "--bill-type", help="Tipo de conta."),
    code: str = typer.Option(..., "--code", help="Codigo da categoria."),
    observations: Optional[str] = typer.Option(
        None, "--observations", help="Observacoes opcionais."
    ),
    parent_code: Optional[str] = typer.Option(
        None, "--parent-code", help="Codigo da categoria pai."
    ),
    output: OutputFormat = typer.Option(
        OutputFormat.json, "--output", "-o", help="Formato: json|table|csv"
    ),
) -> None:
    """Cria uma nova categoria financeira.

    EXAMPLES:
      aegro fin-categories create --description "Insumos" --type EXPENSE --operation-type DEBIT --status ACTIVE --bill-type PAYABLE --code "1.1"
      aegro fin-categories create --description "Sementes" --type EXPENSE --operation-type DEBIT --status ACTIVE --bill-type PAYABLE --code "1.1.1" --parent-code "1.1"
    """
    try:
        farm_name, api_key = require_farm()
        client = get_client()
        body: dict = {
            "description": description,
            "type": cat_type,
            "operationType": operation_type,
            "status": status,
            "billType": bill_type,
            "code": code,
        }
        if observations is not None:
            body["observations"] = observations
        if parent_code is not None:
            body["parentCode"] = parent_code
        result = client.post("/pub/v1/financial-categories", api_key=api_key, json_body=body)
        if result is None:
            typer.echo(f"Categoria financeira criada na fazenda '{farm_name}'.")
        else:
            typer.echo(format_output(result, output))
    except (SystemExit, KeyboardInterrupt):
        raise
    except Exception as exc:
        handle_error(exc)


@fin_categories_app.command("subcategories")
def list_subcategories(
    key: str = typer.Argument(help="Chave unica da categoria pai."),
    element_category: Optional[list[str]] = typer.Option(
        None, "--element-category", help="Categoria de elemento (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 subcategorias de uma categoria financeira.

    EXAMPLES:
      aegro fin-categories subcategories abc123
      aegro fin-categories subcategories abc123 --element-category CAT1 --element-category CAT2
    """
    try:
        _, api_key = require_farm()
        client = get_client()
        body: dict = {
            "requiredPageNumber": page,
            "maximumItemsPerPageCount": 50,
        }
        if element_category:
            body["elementCategories"] = element_category
        result = client.post(
            f"/pub/v1/financial-categories/{validate_key(key)}/filter",
            api_key=api_key,
            json_body=body,
        )
        if result is None:
            typer.echo("Nenhuma subcategoria encontrada.")
            return
        typer.echo(format_output(result, output))
    except (SystemExit, KeyboardInterrupt):
        raise
    except Exception as exc:
        handle_error(exc)
