from __future__ import annotations

import json


from aegro.cli import app


class TestCropsGet:
    def test_get_crop(self, runner, mock_settings, mock_client, temp_state):
        mock_client.get.return_value = {"_id": "crop-1", "name": "Soja 24/25"}
        runner.invoke(app, ["farms", "select", "Fazenda Sul"])
        result = runner.invoke(app, ["crops", "get", "crop-1"])
        assert result.exit_code == 0
        data = json.loads(result.stdout)
        assert data["name"] == "Soja 24/25"
        mock_client.get.assert_called_once_with("/pub/v1/crops/crop-1", api_key="key-1")

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

    def test_get_crop_no_farm(self, runner, mock_settings, temp_state):
        result = runner.invoke(app, ["crops", "get", "crop-1"])
        assert result.exit_code != 0


class TestCropsList:
    def test_list_no_filters(self, runner, mock_settings, mock_client, temp_state):
        mock_client.post.return_value = [{"_id": "c1", "name": "Soja"}]
        runner.invoke(app, ["farms", "select", "Fazenda Sul"])
        result = runner.invoke(app, ["crops", "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

    def test_list_with_date_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, ["crops", "list", "--start-date", "2025-01-01", "--end-date", "2025-12-31"]
        )
        assert result.exit_code == 0
        call_body = mock_client.post.call_args.kwargs["json_body"]
        assert call_body["startDate"] == "2025-01-01"
        assert call_body["endDate"] == "2025-12-31"

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


class TestCropsProrate:
    def test_get_prorate(self, runner, mock_settings, mock_client, temp_state):
        mock_client.get.return_value = {"_id": "pr-1", "name": "Rateio"}
        runner.invoke(app, ["farms", "select", "Fazenda Sul"])
        result = runner.invoke(app, ["crops", "prorate", "pr-1"])
        assert result.exit_code == 0
        mock_client.get.assert_called_once_with("/pub/v1/crop-prorate/pr-1", api_key="key-1")


class TestCropsHarvestDiscounts:
    def test_harvest_discounts(self, runner, mock_settings, mock_client, temp_state):
        mock_client.get.return_value = [{"discount": 2.5}]
        runner.invoke(app, ["farms", "select", "Fazenda Sul"])
        result = runner.invoke(app, ["crops", "harvest-discounts", "crop-1"])
        assert result.exit_code == 0
        mock_client.get.assert_called_once_with(
            "/pub/v1/crops/crop-1/crop-harvest-log-discounts", api_key="key-1"
        )

    def test_harvest_discounts_empty(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, ["crops", "harvest-discounts", "crop-1"])
        assert "nenhum" in result.stdout.lower()


class TestCropsProrates:
    def test_list_prorates(self, runner, mock_settings, mock_client, temp_state):
        mock_client.post.return_value = [{"_id": "pr-1"}]
        runner.invoke(app, ["farms", "select", "Fazenda Sul"])
        result = runner.invoke(app, ["crops", "prorates"])
        assert result.exit_code == 0
        mock_client.post.assert_called_once()
        assert mock_client.post.call_args.args[0] == "/pub/v1/crop-prorate/filter"

    def test_list_prorates_with_filters(self, runner, mock_settings, mock_client, temp_state):
        mock_client.post.return_value = []
        runner.invoke(app, ["farms", "select", "Fazenda Sul"])
        runner.invoke(
            app,
            ["crops", "prorates", "--crop-key", "c1", "--crop-key", "c2", "--status", "ACTIVE"],
        )
        call_body = mock_client.post.call_args.kwargs["json_body"]
        assert call_body["cropKeys"] == ["c1", "c2"]
        assert call_body["statuses"] == ["ACTIVE"]


class TestCropsGlebes:
    def test_list_glebes(self, runner, mock_settings, mock_client, temp_state):
        mock_client.post.return_value = [{"_id": "g1"}]
        runner.invoke(app, ["farms", "select", "Fazenda Sul"])
        result = runner.invoke(app, ["crops", "glebes", "crop-1"])
        assert result.exit_code == 0
        assert mock_client.post.call_args.args[0] == "/pub/v1/crops/crop-1/crop-glebes/filter"

    def test_list_glebes_with_keys(self, runner, mock_settings, mock_client, temp_state):
        mock_client.post.return_value = []
        runner.invoke(app, ["farms", "select", "Fazenda Sul"])
        runner.invoke(app, ["crops", "glebes", "crop-1", "--glebe-key", "g1", "--glebe-key", "g2"])
        call_body = mock_client.post.call_args.kwargs["json_body"]
        assert call_body["cropGlebeKeys"] == ["g1", "g2"]
