from __future__ import annotations

import json


from aegro.cli import app


class TestFarmsList:
    def test_lists_farms_json(self, runner, mock_settings, temp_state):
        result = runner.invoke(app, ["farms", "list"])
        assert result.exit_code == 0
        data = json.loads(result.stdout)
        names = [f["name"] for f in data]
        assert "Fazenda Norte" in names
        assert "Fazenda Sul" in names

    def test_lists_farms_marks_active(self, runner, mock_settings, temp_state):
        runner.invoke(app, ["farms", "select", "Fazenda Sul"])
        result = runner.invoke(app, ["farms", "list"])
        data = json.loads(result.stdout)
        active = [f for f in data if f["active"]]
        assert len(active) == 1
        assert active[0]["name"] == "Fazenda Sul"


class TestFarmsSelect:
    def test_select_valid_farm(self, runner, mock_settings, temp_state):
        result = runner.invoke(app, ["farms", "select", "Fazenda Sul"])
        assert result.exit_code == 0
        assert "Fazenda Sul" in result.stdout

    def test_select_invalid_farm(self, runner, mock_settings, temp_state):
        result = runner.invoke(app, ["farms", "select", "Inexistente"])
        assert result.exit_code == 1


class TestFarmsInfo:
    def test_info_no_farm_selected(self, runner, mock_settings, temp_state):
        result = runner.invoke(app, ["farms", "info"])
        assert result.exit_code != 0

    def test_info_shows_farm_data(self, runner, mock_settings, mock_client, temp_state):
        mock_client.get.return_value = {"name": "Fazenda Sul", "area": 1200}
        runner.invoke(app, ["farms", "select", "Fazenda Sul"])
        result = runner.invoke(app, ["farms", "info"])
        assert result.exit_code == 0
        data = json.loads(result.stdout)
        assert data["name"] == "Fazenda Sul"
        mock_client.get.assert_called_once_with("/pub/v1/farms", api_key="key-1")


class TestActiveFarmEnvVar:
    """AEGRO_ACTIVE_FARM env var overrides state.json for parallel Cowork sessions."""

    def test_env_var_sets_active_without_state_file(
        self, runner, mock_settings, temp_state, monkeypatch
    ):
        monkeypatch.setenv("AEGRO_ACTIVE_FARM", "Fazenda Sul")
        result = runner.invoke(app, ["farms", "list"])
        assert result.exit_code == 0
        data = json.loads(result.stdout)
        active = [f for f in data if f["active"]]
        assert len(active) == 1
        assert active[0]["name"] == "Fazenda Sul"
        assert active[0]["source"] == "env"

    def test_env_var_overrides_state_file(self, runner, mock_settings, temp_state, monkeypatch):
        runner.invoke(app, ["farms", "select", "Fazenda Norte"])
        monkeypatch.setenv("AEGRO_ACTIVE_FARM", "Fazenda Sul")
        result = runner.invoke(app, ["farms", "list"])
        data = json.loads(result.stdout)
        active = [f for f in data if f["active"]][0]
        assert active["name"] == "Fazenda Sul"
        assert active["source"] == "env"

    def test_state_file_used_when_env_unset(self, runner, mock_settings, temp_state):
        runner.invoke(app, ["farms", "select", "Fazenda Norte"])
        result = runner.invoke(app, ["farms", "list"])
        data = json.loads(result.stdout)
        active = [f for f in data if f["active"]][0]
        assert active["name"] == "Fazenda Norte"
        assert active["source"] == "state"

    def test_env_var_empty_is_ignored(self, runner, mock_settings, temp_state, monkeypatch):
        monkeypatch.setenv("AEGRO_ACTIVE_FARM", "   ")
        runner.invoke(app, ["farms", "select", "Fazenda Norte"])
        result = runner.invoke(app, ["farms", "list"])
        data = json.loads(result.stdout)
        active = [f for f in data if f["active"]][0]
        assert active["name"] == "Fazenda Norte"
        assert active["source"] == "state"

    def test_info_uses_env_var(self, runner, mock_settings, mock_client, temp_state, monkeypatch):
        mock_client.get.return_value = {"name": "Fazenda Sul"}
        monkeypatch.setenv("AEGRO_ACTIVE_FARM", "Fazenda Sul")
        result = runner.invoke(app, ["farms", "info"])
        assert result.exit_code == 0
        mock_client.get.assert_called_once_with("/pub/v1/farms", api_key="key-1")

    def test_info_errors_when_env_farm_not_configured(
        self, runner, mock_settings, temp_state, monkeypatch
    ):
        monkeypatch.setenv("AEGRO_ACTIVE_FARM", "Fazenda Inexistente")
        result = runner.invoke(app, ["farms", "info"])
        assert result.exit_code != 0

    def test_select_warns_when_env_set(self, runner, mock_settings, temp_state, monkeypatch):
        monkeypatch.setenv("AEGRO_ACTIVE_FARM", "Fazenda Sul")
        result = runner.invoke(app, ["farms", "select", "Fazenda Norte"])
        assert result.exit_code == 0
        combined = result.stdout + (result.stderr or "")
        assert "AEGRO_ACTIVE_FARM" in combined

    def test_inactive_farms_have_null_source(self, runner, mock_settings, temp_state, monkeypatch):
        monkeypatch.setenv("AEGRO_ACTIVE_FARM", "Fazenda Sul")
        result = runner.invoke(app, ["farms", "list"])
        data = json.loads(result.stdout)
        inactive = [f for f in data if not f["active"]]
        assert all(f["source"] is None for f in inactive)

    def test_require_farm_error_lists_farms_when_multiple(self, runner, mock_settings, temp_state):
        result = runner.invoke(app, ["farms", "info"])
        assert result.exit_code != 0
        err_output = result.stderr or result.stdout
        assert "AEGRO_ACTIVE_FARM" in err_output
