from __future__ import annotations

import json

from aegro.cli import app


class TestCompaniesGet:
    def test_get_company(self, runner, mock_settings, mock_client, temp_state):
        mock_client.get.return_value = {"_id": "co1", "name": "AgroSul Ltda"}
        runner.invoke(app, ["farms", "select", "Fazenda Sul"])
        result = runner.invoke(app, ["companies", "get", "co1"])
        assert result.exit_code == 0
        data = json.loads(result.stdout)
        assert data["name"] == "AgroSul Ltda"
        mock_client.get.assert_called_once_with("/pub/v1/companies/co1", api_key="key-1")

    def test_get_company_not_found(self, runner, mock_settings, mock_client, temp_state):
        mock_client.get.return_value = None
        runner.invoke(app, ["farms", "select", "Fazenda Sul"])
        result = runner.invoke(app, ["companies", "get", "missing"])
        assert result.exit_code == 0
        assert "nao encontrad" in result.stdout.lower()

    def test_get_company_no_farm(self, runner, mock_settings, temp_state):
        result = runner.invoke(app, ["companies", "get", "co1"])
        assert result.exit_code != 0


class TestCompaniesList:
    def test_list_no_filters(self, runner, mock_settings, mock_client, temp_state):
        mock_client.post.return_value = [{"_id": "co1", "name": "AgroSul"}]
        runner.invoke(app, ["farms", "select", "Fazenda Sul"])
        result = runner.invoke(app, ["companies", "list"])
        assert result.exit_code == 0
        data = json.loads(result.stdout)
        assert len(data) == 1
        call_body = mock_client.post.call_args.kwargs["json_body"]
        assert call_body["requiredPageNumber"] == 1
        assert call_body["maximumItemsPerPageCount"] == 50

    def test_list_with_filters(self, runner, mock_settings, mock_client, temp_state):
        mock_client.post.return_value = []
        runner.invoke(app, ["farms", "select", "Fazenda Sul"])
        result = runner.invoke(
            app,
            [
                "companies",
                "list",
                "--search-text",
                "Agro",
                "--fiscal-number-type",
                "CNPJ",
            ],
        )
        assert result.exit_code == 0
        call_body = mock_client.post.call_args.kwargs["json_body"]
        assert call_body["searchText"] == "Agro"
        assert call_body["fiscalNumberType"] == "CNPJ"

    def test_list_with_page(self, runner, mock_settings, mock_client, temp_state):
        mock_client.post.return_value = []
        runner.invoke(app, ["farms", "select", "Fazenda Sul"])
        runner.invoke(app, ["companies", "list", "--page", "3"])
        call_body = mock_client.post.call_args.kwargs["json_body"]
        assert call_body["requiredPageNumber"] == 3

    def test_list_empty_result(self, runner, mock_settings, mock_client, temp_state):
        mock_client.post.return_value = None
        runner.invoke(app, ["farms", "select", "Fazenda Sul"])
        result = runner.invoke(app, ["companies", "list"])
        assert result.exit_code == 0
        assert "nenhum" in result.stdout.lower()


class TestCompaniesCreate:
    def test_create_company(self, runner, mock_settings, mock_client, temp_state):
        mock_client.post.return_value = {"_id": "co-new", "name": "AgroSul Ltda"}
        runner.invoke(app, ["farms", "select", "Fazenda Sul"])
        result = runner.invoke(
            app,
            [
                "companies",
                "create",
                "--name",
                "AgroSul Ltda",
                "--type",
                "SUPPLIER",
                "--fiscal-code",
                "12345678000199",
                "--fiscal-type",
                "CNPJ",
            ],
        )
        assert result.exit_code == 0
        data = json.loads(result.stdout)
        assert data["_id"] == "co-new"
        call_body = mock_client.post.call_args.kwargs["json_body"]
        assert call_body["name"] == "AgroSul Ltda"
        assert call_body["types"] == ["SUPPLIER"]
        assert call_body["fiscalNumber"]["code"] == "12345678000199"
        assert call_body["fiscalNumber"]["fiscalNumberType"] == "CNPJ"
        assert call_body["fiscalNumber"]["countryCode"] == "BR"

    def test_create_company_multiple_types(self, runner, mock_settings, mock_client, temp_state):
        mock_client.post.return_value = None
        runner.invoke(app, ["farms", "select", "Fazenda Sul"])
        result = runner.invoke(
            app,
            [
                "companies",
                "create",
                "--name",
                "Multipla",
                "--type",
                "CLIENT",
                "--type",
                "SUPPLIER",
            ],
        )
        assert result.exit_code == 0
        assert "criada" in result.stdout.lower()
        call_body = mock_client.post.call_args.kwargs["json_body"]
        assert call_body["types"] == ["CLIENT", "SUPPLIER"]

    def test_create_company_with_optional_fields(
        self, runner, mock_settings, mock_client, temp_state
    ):
        mock_client.post.return_value = {"_id": "co-new"}
        runner.invoke(app, ["farms", "select", "Fazenda Sul"])
        result = runner.invoke(
            app,
            [
                "companies",
                "create",
                "--name",
                "JS Agro",
                "--trade-name",
                "JS Agropecuaria",
                "--legal-name",
                "JS Agro Ltda",
                "--observations",
                "Fornecedor de sementes",
            ],
        )
        assert result.exit_code == 0
        call_body = mock_client.post.call_args.kwargs["json_body"]
        assert call_body["tradeName"] == "JS Agropecuaria"
        assert call_body["legalName"] == "JS Agro Ltda"
        assert call_body["observations"] == "Fornecedor de sementes"

    def test_create_company_fiscal_country(self, runner, mock_settings, mock_client, temp_state):
        mock_client.post.return_value = None
        runner.invoke(app, ["farms", "select", "Fazenda Sul"])
        runner.invoke(
            app,
            [
                "companies",
                "create",
                "--name",
                "Empresa AR",
                "--fiscal-code",
                "999",
                "--fiscal-type",
                "CUIT",
                "--fiscal-country",
                "AR",
            ],
        )
        call_body = mock_client.post.call_args.kwargs["json_body"]
        assert call_body["fiscalNumber"]["countryCode"] == "AR"

    def test_create_company_no_farm(self, runner, mock_settings, temp_state):
        result = runner.invoke(
            app,
            ["companies", "create", "--name", "Empresa"],
        )
        assert result.exit_code != 0


class TestCompaniesUpdate:
    def test_update_company(self, runner, mock_settings, mock_client, temp_state):
        mock_client.put.return_value = {"_id": "c1", "name": "Novo"}
        runner.invoke(app, ["farms", "select", "Fazenda Sul"])
        result = runner.invoke(
            app,
            [
                "companies",
                "update",
                "company::abc",
                "--name",
                "Novo",
                "--type",
                "PROVIDER",
                "--fiscal-code",
                "12345678000199",
                "--fiscal-type",
                "CNPJ",
                "--trade-name",
                "Novo Fantasia",
            ],
        )
        assert result.exit_code == 0
        call = mock_client.put.call_args
        assert call.args[0] == "/pub/v1/companies/company::abc"
        body = call.kwargs["json_body"]
        assert body["name"] == "Novo"
        assert body["types"] == ["PROVIDER"]
        assert body["fiscalNumber"]["code"] == "12345678000199"
        assert body["fiscalNumber"]["fiscalNumberType"] == "CNPJ"
        assert body["tradeName"] == "Novo Fantasia"

    def test_update_no_farm(self, runner, mock_settings, temp_state):
        result = runner.invoke(app, ["companies", "update", "c1", "--name", "X"])
        assert result.exit_code != 0
