"""Tests for apps:status — SDK + CLI."""

from __future__ import annotations

import pytest
from click.testing import CliRunner

from kuberoku.cli.main import cli
from kuberoku.exceptions import AppNotFoundError
from kuberoku.factory import KuberokuFactory
from tests.e2e.helpers import poll_until
from tests.services.conftest import _create_fake_pod


class TestAppsStatusSDK:
    """SDK-level tests for AppsService.status()."""

    def test_status_empty_app(self, factory: KuberokuFactory) -> None:
        factory.apps.create("myapi")
        st = factory.apps.status("myapi")
        assert st.app.name == "myapi"
        assert st.dynos == []
        assert st.config_count == 0
        assert st.secret_count == 0
        assert st.addons == []
        assert st.domains == []
        assert st.latest_release is None
        assert st.ports == {}

    def test_status_with_deploy(
        self, factory: KuberokuFactory, request: pytest.FixtureRequest
    ) -> None:
        factory.apps.create("myapi")
        factory.deploy.deploy("myapi", image="nginx:1.27", wait=False)
        if request.config.getoption("--backend") == "fake":
            _create_fake_pod(factory, "myapi", "web", "pod-a", image="nginx:1.27")
        else:
            # Real K8s: deployment creates its own pod — poll until visible
            poll_until(
                fn=lambda: factory.apps.status("myapi"),
                predicate=lambda st: len(st.dynos) >= 1,
                timeout=60,
                interval=1,
                message="Pod never appeared in status after deploy",
            )
        st = factory.apps.status("myapi")
        assert len(st.dynos) >= 1
        assert st.dynos[0].process_type == "web"
        assert st.latest_release is not None
        assert st.latest_release.version == 1

    def test_status_with_config(self, factory: KuberokuFactory) -> None:
        factory.apps.create("myapi")
        factory.deploy.deploy("myapi", image="nginx:1.27", wait=False)
        factory.config.set("myapi", {"DB_URL": "postgres://x", "REDIS_URL": "redis://y"})
        factory.config.set("myapi", {"SECRET_KEY": "abc"}, secret=True)
        st = factory.apps.status("myapi")
        assert st.config_count == 2
        assert st.secret_count == 1

    def test_status_with_addons(self, factory: KuberokuFactory) -> None:
        factory.apps.create("myapi")
        factory.addons.create("myapi", "postgres")
        st = factory.apps.status("myapi")
        assert len(st.addons) == 1
        assert st.addons[0].addon_type == "postgres"

    def test_status_app_not_found(self, factory: KuberokuFactory) -> None:
        with pytest.raises(AppNotFoundError, match="noapp"):
            factory.apps.status("noapp")

    def test_status_maintenance_flag(self, factory: KuberokuFactory) -> None:
        factory.apps.create("myapi")
        factory.deploy.deploy("myapi", image="nginx:1.27", wait=False)
        factory.apps.maintenance_on("myapi")
        st = factory.apps.status("myapi")
        assert st.app.maintenance is True


class TestAppsStatusCLI:
    """CLI-level tests for apps:status."""

    def test_status_cli(self, cli_runner: CliRunner, factory: KuberokuFactory) -> None:
        factory.apps.create("myapi")
        result = cli_runner.invoke(cli, ["apps:status", "myapi"], obj={"factory": factory})
        assert result.exit_code == 0
        assert "=== myapi" in result.output
        assert "Maintenance:  off" in result.output

    def test_status_cli_space_syntax(
        self, cli_runner: CliRunner, factory: KuberokuFactory
    ) -> None:
        factory.apps.create("myapi")
        result = cli_runner.invoke(cli, ["apps", "status", "myapi"], obj={"factory": factory})
        assert result.exit_code == 0
        assert "=== myapi" in result.output

    def test_status_cli_with_release_and_processes(
        self,
        cli_runner: CliRunner,
        factory: KuberokuFactory,
        request: pytest.FixtureRequest,
    ) -> None:
        """Status CLI renders release, processes, config, and addons."""
        factory.apps.create("myapi")
        factory.deploy.deploy("myapi", image="nginx:1.27", wait=False)
        if request.config.getoption("--backend") == "fake":
            _create_fake_pod(factory, "myapi", "web", "pod-a", image="nginx:1.27")
        else:
            # Real K8s: wait for pod before checking CLI output
            poll_until(
                fn=lambda: factory.apps.status("myapi"),
                predicate=lambda st: len(st.dynos) >= 1,
                timeout=60,
                interval=1,
                message="Pod never appeared in status after deploy",
            )
        factory.config.set("myapi", {"DB": "pg://x"})
        factory.config.set("myapi", {"KEY": "secret"}, secret=True)
        factory.addons.create("myapi", "postgres")
        result = cli_runner.invoke(cli, ["apps:status", "myapi"], obj={"factory": factory})
        assert result.exit_code == 0
        output = result.output
        # Release line
        assert "Release:" in output
        assert "(Config change" in output or "(Deploy" in output
        # Processes section with web
        assert "Processes:" in output
        assert "web" in output
        assert "running" in output
        assert "nginx:1.27" in output
        assert "ports: 8080/tcp" in output
        # Config count
        assert "2 vars (1 secrets)" in output
        # Addons
        assert "postgres (running)" in output
        # Domains
        assert "Domains:" in output
        # Maintenance off
        assert "Maintenance:  off" in output
