"""Tests for appxen update command."""

from unittest.mock import patch, MagicMock

from typer.testing import CliRunner

from appxen_cli.main import app


class TestUpdate:

    @patch("appxen_cli.commands.update.get_latest_version", return_value="0.2.2")
    @patch("appxen_cli.commands.update.__version__", "0.2.2")
    def test_already_up_to_date(self, mock_get):
        runner = CliRunner()
        result = runner.invoke(app, ["update"])
        assert result.exit_code == 0
        assert "Already up to date" in result.output

    @patch("appxen_cli.commands.update.subprocess.run")
    @patch("appxen_cli.commands.update._is_pipx_install", return_value=True)
    @patch("appxen_cli.commands.update.get_latest_version", return_value="0.3.0")
    @patch("appxen_cli.commands.update.__version__", "0.2.2")
    def test_update_pipx(self, mock_get, mock_pipx, mock_run):
        mock_run.return_value = MagicMock(returncode=0)
        runner = CliRunner()
        result = runner.invoke(app, ["update"])
        assert result.exit_code == 0
        assert "Updated to" in result.output
        mock_run.assert_called_once()
        cmd = mock_run.call_args[0][0]
        assert cmd[0] == "pipx"

    @patch("appxen_cli.commands.update.subprocess.run")
    @patch("appxen_cli.commands.update._is_pipx_install", return_value=False)
    @patch("appxen_cli.commands.update.get_latest_version", return_value="0.3.0")
    @patch("appxen_cli.commands.update.__version__", "0.2.2")
    def test_update_pip(self, mock_get, mock_pipx, mock_run):
        mock_run.return_value = MagicMock(returncode=0)
        runner = CliRunner()
        result = runner.invoke(app, ["update"])
        assert result.exit_code == 0
        assert "Updated to" in result.output
        mock_run.assert_called_once()
        cmd = mock_run.call_args[0][0]
        assert "pip" in cmd[-2] or cmd[-1] == "appxen"

    @patch("appxen_cli.commands.update.get_latest_version", return_value="0.3.0")
    @patch("appxen_cli.commands.update.__version__", "0.2.2")
    def test_check_only(self, mock_get):
        runner = CliRunner()
        result = runner.invoke(app, ["update", "--check"])
        assert result.exit_code == 0
        assert "Update available" in result.output
        assert "appxen update" in result.output

    @patch("appxen_cli.commands.update.get_latest_version", return_value="0.2.2")
    @patch("appxen_cli.commands.update.__version__", "0.2.2")
    def test_check_already_latest(self, mock_get):
        runner = CliRunner()
        result = runner.invoke(app, ["update", "--check"])
        assert result.exit_code == 0
        assert "Already up to date" in result.output

    @patch("appxen_cli.commands.update.get_latest_version", return_value=None)
    def test_unreachable(self, mock_get):
        runner = CliRunner()
        result = runner.invoke(app, ["update"])
        assert result.exit_code == 1
        assert "Could not check" in result.output

    @patch("appxen_cli.commands.update.subprocess.run")
    @patch("appxen_cli.commands.update._is_pipx_install", return_value=False)
    @patch("appxen_cli.commands.update.get_latest_version", return_value="0.3.0")
    @patch("appxen_cli.commands.update.__version__", "0.2.2")
    def test_update_failure(self, mock_get, mock_pipx, mock_run):
        mock_run.return_value = MagicMock(returncode=1, stderr="something broke")
        runner = CliRunner()
        result = runner.invoke(app, ["update"])
        assert result.exit_code == 1
        assert "Update failed" in result.output
