from __future__ import annotations

import json
from unittest.mock import MagicMock

from typer.testing import CliRunner

from aegro.cli import app

runner = CliRunner()


class TestAuthLogin:
    def test_login_with_farm_name(self, tmp_path, monkeypatch):
        monkeypatch.setattr("aegro.cli._auth.get_config_dir", lambda: tmp_path)
        monkeypatch.delenv("AEGRO_FARMS", raising=False)
        monkeypatch.delenv("AEGRO_FARMS_FILE", raising=False)
        result = runner.invoke(
            app,
            ["auth", "login", "--farm-name", "Fazenda Sul", "--api-key", "key-123"],
        )
        assert result.exit_code == 0
        assert "Fazenda Sul" in result.stdout
        cred_file = tmp_path / "credentials.json"
        assert cred_file.exists()
        data = json.loads(cred_file.read_text())
        assert data["farms"]["Fazenda Sul"] == "key-123"

    def test_login_auto_detects_farm_name(self, tmp_path, monkeypatch):
        monkeypatch.setattr("aegro.cli._auth.get_config_dir", lambda: tmp_path)
        monkeypatch.delenv("AEGRO_FARMS", raising=False)
        monkeypatch.delenv("AEGRO_FARMS_FILE", raising=False)
        mock_client = MagicMock()
        mock_client.get.return_value = {"key": "farm-1", "name": "Fazenda Norte"}
        monkeypatch.setattr("aegro.cli._client.SyncAegroClient", lambda: mock_client)
        result = runner.invoke(app, ["auth", "login", "--api-key", "key-abc"])
        assert result.exit_code == 0
        assert "Fazenda Norte" in result.stdout
        data = json.loads((tmp_path / "credentials.json").read_text())
        assert data["farms"]["Fazenda Norte"] == "key-abc"

    def test_login_auto_detect_api_error(self, tmp_path, monkeypatch):
        monkeypatch.setattr("aegro.cli._auth.get_config_dir", lambda: tmp_path)
        monkeypatch.delenv("AEGRO_FARMS", raising=False)
        monkeypatch.delenv("AEGRO_FARMS_FILE", raising=False)
        mock_client = MagicMock()
        mock_client.get.side_effect = Exception("Connection refused")
        monkeypatch.setattr("aegro.cli._client.SyncAegroClient", lambda: mock_client)
        result = runner.invoke(app, ["auth", "login", "--api-key", "bad-key"])
        assert result.exit_code != 0

    def test_login_auto_detect_no_name(self, tmp_path, monkeypatch):
        monkeypatch.setattr("aegro.cli._auth.get_config_dir", lambda: tmp_path)
        monkeypatch.delenv("AEGRO_FARMS", raising=False)
        monkeypatch.delenv("AEGRO_FARMS_FILE", raising=False)
        mock_client = MagicMock()
        mock_client.get.return_value = {"key": "farm-1"}
        monkeypatch.setattr("aegro.cli._client.SyncAegroClient", lambda: mock_client)
        result = runner.invoke(app, ["auth", "login", "--api-key", "key-no-name"])
        assert result.exit_code != 0

    def test_login_adds_to_existing(self, tmp_path, monkeypatch):
        monkeypatch.setattr("aegro.cli._auth.get_config_dir", lambda: tmp_path)
        monkeypatch.delenv("AEGRO_FARMS", raising=False)
        monkeypatch.delenv("AEGRO_FARMS_FILE", raising=False)
        runner.invoke(app, ["auth", "login", "--farm-name", "A", "--api-key", "ka"])
        runner.invoke(app, ["auth", "login", "--farm-name", "B", "--api-key", "kb"])
        data = json.loads((tmp_path / "credentials.json").read_text())
        assert "A" in data["farms"]
        assert "B" in data["farms"]

    def test_login_rejects_empty_key(self, tmp_path, monkeypatch):
        monkeypatch.setattr("aegro.cli._auth.get_config_dir", lambda: tmp_path)
        result = runner.invoke(app, ["auth", "login", "--farm-name", "Farm", "--api-key", "   "])
        assert result.exit_code != 0


class TestAuthStatus:
    def test_status_no_credentials(self, tmp_path, monkeypatch):
        monkeypatch.setattr("aegro.cli._auth.get_config_dir", lambda: tmp_path)
        monkeypatch.delenv("AEGRO_FARMS", raising=False)
        monkeypatch.delenv("AEGRO_FARMS_FILE", raising=False)
        result = runner.invoke(app, ["auth", "status"])
        assert result.exit_code == 0
        assert "nenhuma" in result.stdout.lower()

    def test_status_with_credentials(self, tmp_path, monkeypatch):
        monkeypatch.setattr("aegro.cli._auth.get_config_dir", lambda: tmp_path)
        monkeypatch.delenv("AEGRO_FARMS", raising=False)
        monkeypatch.delenv("AEGRO_FARMS_FILE", raising=False)
        runner.invoke(app, ["auth", "login", "--farm-name", "Farm X", "--api-key", "key-x"])
        result = runner.invoke(app, ["auth", "status"])
        assert result.exit_code == 0
        assert "Farm X" in result.stdout

    def test_status_shows_env_source(self, monkeypatch):
        monkeypatch.setenv("AEGRO_FARMS", '{"EnvFarm": "key-env"}')
        result = runner.invoke(app, ["auth", "status"])
        assert result.exit_code == 0
        assert "EnvFarm" in result.stdout


class TestAuthLogout:
    def test_logout_removes_credentials(self, tmp_path, monkeypatch):
        monkeypatch.setattr("aegro.cli._auth.get_config_dir", lambda: tmp_path)
        monkeypatch.delenv("AEGRO_FARMS", raising=False)
        monkeypatch.delenv("AEGRO_FARMS_FILE", raising=False)
        runner.invoke(app, ["auth", "login", "--farm-name", "Farm", "--api-key", "k"])
        result = runner.invoke(app, ["auth", "logout"])
        assert result.exit_code == 0
        assert not (tmp_path / "credentials.json").exists()

    def test_logout_when_no_credentials(self, tmp_path, monkeypatch):
        monkeypatch.setattr("aegro.cli._auth.get_config_dir", lambda: tmp_path)
        result = runner.invoke(app, ["auth", "logout"])
        assert result.exit_code == 0
