from __future__ import annotations

import json

from aegro.cli import app


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

    def test_get_tag_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, ["tags", "get", "missing"])
        assert result.exit_code == 0
        assert "nao encontrad" in result.stdout.lower()

    def test_get_tag_no_farm(self, runner, mock_settings, temp_state):
        result = runner.invoke(app, ["tags", "get", "t1"])
        assert result.exit_code != 0


class TestTagsList:
    def test_list_no_filters(self, runner, mock_settings, mock_client, temp_state):
        mock_client.post.return_value = [{"_id": "t1", "name": "Organico"}]
        runner.invoke(app, ["farms", "select", "Fazenda Sul"])
        result = runner.invoke(app, ["tags", "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,
            [
                "tags",
                "list",
                "--relation-type",
                "CROP",
                "--relation-type",
                "ACTIVITY",
                "--status",
                "ACTIVE",
                "--search-text",
                "soja",
            ],
        )
        assert result.exit_code == 0
        call_body = mock_client.post.call_args.kwargs["json_body"]
        assert call_body["relationTypes"] == ["CROP", "ACTIVITY"]
        assert call_body["statuses"] == ["ACTIVE"]
        assert call_body["searchText"] == "soja"

    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, ["tags", "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, ["tags", "list"])
        assert result.exit_code == 0
        assert "nenhum" in result.stdout.lower()


class TestTagsCreate:
    def test_create_tag(self, runner, mock_settings, mock_client, temp_state):
        mock_client.post.return_value = {"_id": "t-new", "name": "Organico"}
        runner.invoke(app, ["farms", "select", "Fazenda Sul"])
        result = runner.invoke(
            app,
            [
                "tags",
                "create",
                "--name",
                "Organico",
                "--relation-type",
                "CROP",
            ],
        )
        assert result.exit_code == 0
        data = json.loads(result.stdout)
        assert data["_id"] == "t-new"
        call_body = mock_client.post.call_args.kwargs["json_body"]
        assert call_body["name"] == "Organico"
        assert call_body["relationType"] == "CROP"
        assert "status" not in call_body

    def test_create_tag_with_status(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,
            [
                "tags",
                "create",
                "--name",
                "Urgente",
                "--relation-type",
                "ACTIVITY",
                "--status",
                "ACTIVE",
            ],
        )
        assert result.exit_code == 0
        assert "criada" in result.stdout.lower()
        call_body = mock_client.post.call_args.kwargs["json_body"]
        assert call_body["status"] == "ACTIVE"

    def test_create_tag_no_farm(self, runner, mock_settings, temp_state):
        result = runner.invoke(
            app,
            ["tags", "create", "--name", "Tag", "--relation-type", "CROP"],
        )
        assert result.exit_code != 0


class TestTagsUpdate:
    def test_update_tag(self, runner, mock_settings, mock_client, temp_state):
        mock_client.put.return_value = {"_id": "t1", "name": "Novo"}
        runner.invoke(app, ["farms", "select", "Fazenda Sul"])
        result = runner.invoke(
            app,
            [
                "tags",
                "update",
                "tag::abc",
                "--name",
                "Novo",
                "--relation-type",
                "ACTIVITY",
                "--status",
                "ARCHIVED",
            ],
        )
        assert result.exit_code == 0
        call = mock_client.put.call_args
        assert call.args[0] == "/pub/v1/tags/tag::abc"
        body = call.kwargs["json_body"]
        assert body["name"] == "Novo"
        assert body["relationType"] == "ACTIVITY"
        assert body["status"] == "ARCHIVED"

    def test_update_no_farm(self, runner, mock_settings, temp_state):
        result = runner.invoke(
            app,
            ["tags", "update", "t1", "--name", "N", "--relation-type", "CROP"],
        )
        assert result.exit_code != 0
