"""Tests for apps:maintenance:on/off — 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 kuberoku.k8s import resources


class TestAppsMaintenanceSDK:
    """SDK-level tests for AppsService.maintenance_on/off/status()."""

    def test_maintenance_status_default_off(self, factory: KuberokuFactory) -> None:
        factory.apps.create("myapi")
        maint = factory.apps.maintenance_status("myapi")
        assert maint.enabled is False
        assert maint.app_wide is False
        assert maint.since is None
        assert maint.services == ()
        assert maint.saved_replicas == {}

    def test_maintenance_on(self, factory: KuberokuFactory) -> None:
        factory.apps.create("myapi")
        factory.deploy.deploy("myapi", image="nginx:1.27", wait=False)
        maint = factory.apps.maintenance_on("myapi")
        assert maint.enabled is True
        assert maint.app_wide is True
        assert maint.since is not None
        assert "web" in maint.saved_replicas
        assert maint.saved_replicas["web"] == 1

    def test_maintenance_on_scales_to_zero(self, factory: KuberokuFactory) -> None:
        factory.apps.create("myapi")
        factory.deploy.deploy("myapi", image="nginx:1.27", wait=False)
        factory.apps.maintenance_on("myapi")
        dep_name = resources.safe_name(factory.prefix, "myapi", "web")
        dep = factory.k8s.get_deployment(factory.namespace, dep_name)
        assert dep["spec"]["replicas"] == 0

    def test_maintenance_off_restores(self, factory: KuberokuFactory) -> None:
        factory.apps.create("myapi")
        factory.deploy.deploy("myapi", image="nginx:1.27", wait=False)
        # Scale to 3 via SDK (handles 409 retries on real K8s)
        factory.ps.scale("myapi", {"web": 3})
        # Enable then disable
        factory.apps.maintenance_on("myapi")
        factory.apps.maintenance_off("myapi")
        dep_name = resources.safe_name(factory.prefix, "myapi", "web")
        dep = factory.k8s.get_deployment(factory.namespace, dep_name)
        assert dep["spec"]["replicas"] == 3

    def test_maintenance_off_clears_flag(self, factory: KuberokuFactory) -> None:
        factory.apps.create("myapi")
        factory.deploy.deploy("myapi", image="nginx:1.27", wait=False)
        factory.apps.maintenance_on("myapi")
        factory.apps.maintenance_off("myapi")
        maint = factory.apps.maintenance_status("myapi")
        assert maint.enabled is False
        assert maint.app_wide is False
        assert maint.since is None

    def test_maintenance_on_idempotent(self, factory: KuberokuFactory) -> None:
        factory.apps.create("myapi")
        factory.deploy.deploy("myapi", image="nginx:1.27", wait=False)
        factory.apps.maintenance_on("myapi")
        # Second call should not fail
        maint = factory.apps.maintenance_on("myapi")
        assert maint.enabled is True

    def test_maintenance_info_reflects_state(self, factory: KuberokuFactory) -> None:
        factory.apps.create("myapi")
        factory.deploy.deploy("myapi", image="nginx:1.27", wait=False)
        app_before = factory.apps.info("myapi")
        assert app_before.maintenance is False
        factory.apps.maintenance_on("myapi")
        app_after = factory.apps.info("myapi")
        assert app_after.maintenance is True

    def test_maintenance_on_step_callbacks(self, factory: KuberokuFactory) -> None:
        factory.apps.create("myapi")
        factory.deploy.deploy("myapi", image="nginx:1.27", wait=False)
        steps: list[str] = []
        factory.apps.maintenance_on("myapi", on_step=steps.append)
        assert len(steps) >= 2

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

    def test_maintenance_off_when_not_on(self, factory: KuberokuFactory) -> None:
        factory.apps.create("myapi")
        factory.deploy.deploy("myapi", image="nginx:1.27", wait=False)
        # Should not fail
        maint = factory.apps.maintenance_off("myapi")
        assert maint.enabled is False

    def test_maintenance_multi_process(self, factory: KuberokuFactory) -> None:
        factory.apps.create("myapi")
        factory.deploy.deploy("myapi", image="nginx:1.27", wait=False)
        factory.deploy.deploy(
            "myapi",
            image="worker:v1",
            process_type="worker",
            ports=None,
            wait=False,
        )
        maint = factory.apps.maintenance_on("myapi")
        assert "web" in maint.saved_replicas
        assert "worker" in maint.saved_replicas
        # Verify both scaled to 0
        for ptype in ["web", "worker"]:
            dep_name = resources.safe_name(factory.prefix, "myapi", ptype)
            dep = factory.k8s.get_deployment(factory.namespace, dep_name)
            assert dep["spec"]["replicas"] == 0


class TestAppsMaintenanceCLI:
    """CLI-level tests for apps:maintenance commands."""

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

    def test_maintenance_on_cli(self, cli_runner: CliRunner, factory: KuberokuFactory) -> None:
        factory.apps.create("myapi")
        factory.deploy.deploy("myapi", image="nginx:1.27", wait=False)
        result = cli_runner.invoke(
            cli, ["apps", "maintenance", "on", "myapi"], obj={"factory": factory}
        )
        assert result.exit_code == 0
        assert "enabled" in result.output

    def test_maintenance_off_cli(self, cli_runner: CliRunner, factory: KuberokuFactory) -> None:
        factory.apps.create("myapi")
        factory.deploy.deploy("myapi", image="nginx:1.27", wait=False)
        factory.apps.maintenance_on("myapi")
        result = cli_runner.invoke(
            cli, ["apps", "maintenance", "off", "myapi"], obj={"factory": factory}
        )
        assert result.exit_code == 0
        assert "disabled" in result.output

    def test_maintenance_colon_syntax_on(
        self, cli_runner: CliRunner, factory: KuberokuFactory
    ) -> None:
        factory.apps.create("myapi")
        factory.deploy.deploy("myapi", image="nginx:1.27", wait=False)
        result = cli_runner.invoke(cli, ["apps:maintenance:on", "myapi"], obj={"factory": factory})
        assert result.exit_code == 0
        assert "enabled" in result.output
