from __future__ import annotations

from types import SimpleNamespace
from pathlib import Path

import pytest

from worai import cli as mod
from worai.errors import ConfigError, WoraError


def test_truthy_and_should_check_updates(monkeypatch: pytest.MonkeyPatch) -> None:
    assert mod._is_truthy("true")
    assert mod._is_truthy("1")
    assert not mod._is_truthy("0")
    assert not mod._is_truthy(None)

    ctx = SimpleNamespace(obj={"quiet": False})
    monkeypatch.delenv("PYTEST_CURRENT_TEST", raising=False)
    monkeypatch.delenv("WORAI_DISABLE_UPDATE_CHECK", raising=False)
    monkeypatch.setattr(mod.sys, "argv", ["worai", "graph"])
    assert mod._should_check_updates(ctx)

    monkeypatch.setenv("WORAI_DISABLE_UPDATE_CHECK", "1")
    assert not mod._should_check_updates(ctx)


def test_emit_update_notice_and_run_error(monkeypatch: pytest.MonkeyPatch) -> None:
    monkeypatch.setattr(mod, "_should_check_updates", lambda _ctx: True)
    monkeypatch.setattr(mod, "check_for_update", lambda *_a, **_k: SimpleNamespace(update_available=True, latest_version="9.9.9", current_version="1.0.0", upgrade_command=["pip", "install", "-U", "worai"]))
    seen = {}
    monkeypatch.setattr(mod.typer, "secho", lambda msg, **_k: seen.setdefault("msg", msg))
    mod._emit_update_notice(SimpleNamespace(obj={}))
    assert "Update available for worai" in seen["msg"]

    monkeypatch.setattr(mod, "_should_check_updates", lambda _ctx: False)
    mod._emit_update_notice(SimpleNamespace(obj={}))

    monkeypatch.setattr(mod, "app", lambda: (_ for _ in ()).throw(WoraError("boom", exit_code=7)))
    with pytest.raises(SystemExit) as exc:
        mod.run()
    assert exc.value.code == 7


def test_resolve_log_level_prefers_cli_env_config(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
    cfg = tmp_path / "worai.toml"
    cfg.write_text(
        "log_level = 'warning'\n\n[profiles.acme]\nlog_level = 'error'\n",
        encoding="utf-8",
    )

    assert mod._resolve_log_level(cli_value="debug", config_path=cfg, profile="acme", env={}) == "debug"
    assert (
        mod._resolve_log_level(
            cli_value=None,
            config_path=cfg,
            profile="acme",
            env={"WORAI_LOG_LEVEL": "info"},
        )
        == "info"
    )
    assert mod._resolve_log_level(cli_value=None, config_path=cfg, profile="acme", env={}) == "error"
    assert mod._resolve_log_level(cli_value=None, config_path=cfg, profile=None, env={}) == "warning"


def test_resolve_log_level_supports_profiles_base_fallback(tmp_path: Path) -> None:
    cfg = tmp_path / "worai.toml"
    cfg.write_text(
        "[profiles._base]\nlog_level='warning'\n\n[profiles.acme]\napi_key='wl_123'\n",
        encoding="utf-8",
    )

    assert mod._resolve_log_level_from_config(cfg, "acme") == "warning"
    assert mod._resolve_log_level_from_config(cfg, None) == "warning"

    cfg.write_text(
        "[profiles._base]\nlog_level='warning'\n\n[profiles.acme]\nlog_level='error'\n",
        encoding="utf-8",
    )
    assert mod._resolve_log_level_from_config(cfg, "acme") == "error"


def test_resolve_log_level_from_config_validates_values(tmp_path: Path) -> None:
    cfg = tmp_path / "worai.toml"
    cfg.write_text("log_level = 3\n", encoding="utf-8")
    with pytest.raises(ConfigError, match="must be a string"):
        mod._resolve_log_level_from_config(cfg, None)

    cfg.write_text("log_level = 'verbose'\n", encoding="utf-8")
    with pytest.raises(ConfigError, match="debug, info, warning, error"):
        mod._resolve_log_level_from_config(cfg, None)


def test_main_uses_config_log_level_when_cli_and_env_missing(
    tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
    cfg = tmp_path / "worai.toml"
    cfg.write_text("[profiles.acme]\nlog_level='warning'\n", encoding="utf-8")

    seen = {}
    monkeypatch.setattr(mod, "_load_dotenv_defaults", lambda: None)
    monkeypatch.setattr(mod, "_emit_update_notice", lambda _ctx: None)
    monkeypatch.setattr(mod, "resolve_config_path", lambda _config, env=None: cfg)
    monkeypatch.setattr(mod, "setup_logging", lambda level, fmt, quiet: seen.update({"level": level, "fmt": fmt, "quiet": quiet}))

    ctx = SimpleNamespace(obj={})
    mod.main(ctx, config=None, profile="acme", log_level=None, log_format="text", quiet=False)

    assert seen["level"] == "warning"
    assert ctx.obj["log_level"] == "warning"
