from __future__ import annotations

import os
import pytest

from pulselog.config import Config
from pulselog.levels import Level


class TestConfig:
    def test_defaults(self):
        cfg = Config.load()
        assert cfg.host == "localhost"
        assert cfg.port == 5678
        assert cfg.auto_open is True or cfg.auto_open is False  # depends on CI env
        assert cfg.dashboard is True
        assert cfg.level == "DEBUG"
        assert cfg.level_value == Level.DEBUG.value

    def test_kwargs_win_over_env(self):
        os.environ["PULSELOG_PORT"] = "9000"
        try:
            cfg = Config.load(port=9999)
            assert cfg.port == 9999
        finally:
            del os.environ["PULSELOG_PORT"]

    def test_env_var_port(self):
        os.environ["PULSELOG_PORT"] = "8765"
        try:
            cfg = Config.load()
            assert cfg.port == 8765
        finally:
            del os.environ["PULSELOG_PORT"]

    def test_env_var_bool_true_variants(self):
        for val in ("true", "True", "1", "yes"):
            os.environ["PULSELOG_DASHBOARD"] = val
            try:
                cfg = Config.load()
                assert cfg.dashboard is True, f"Failed for value {val!r}"
            finally:
                del os.environ["PULSELOG_DASHBOARD"]

    def test_env_var_bool_false_variants(self):
        for val in ("false", "False", "0", "no"):
            os.environ["PULSELOG_DASHBOARD"] = val
            try:
                cfg = Config.load()
                assert cfg.dashboard is False, f"Failed for value {val!r}"
            finally:
                del os.environ["PULSELOG_DASHBOARD"]

    def test_invalid_port_raises(self):
        with pytest.raises(ValueError, match="Port must be"):
            Config.load(port=80)

    def test_invalid_port_too_high(self):
        with pytest.raises(ValueError):
            Config.load(port=99999)

    def test_level_value_derived(self):
        cfg = Config.load(level="WARNING")
        from pulselog.levels import Level
        assert cfg.level_value == Level.WARNING.value

    def test_none_kwargs_ignored(self):
        cfg = Config.load(host=None, port=None)
        assert cfg.host == "localhost"
        assert cfg.port == 5678

    def test_ci_disables_auto_open(self):
        os.environ["CI"] = "true"
        os.environ.pop("PULSELOG_AUTO_OPEN", None)
        try:
            cfg = Config.load(auto_open=True)
            # CI env should override auto_open to False
            assert cfg.auto_open is False
        finally:
            del os.environ["CI"]

    def test_parse_bool_invalid_raises(self):
        from pulselog.config import _parse_bool
        with pytest.raises(ValueError, match="Cannot parse"):
            _parse_bool("maybe")

    def test_env_var_worker_interval(self):
        os.environ["PULSELOG_WORKER_INTERVAL"] = "0.02"
        try:
            cfg = Config.load()
            assert cfg.worker_interval == 0.02
        finally:
            del os.environ["PULSELOG_WORKER_INTERVAL"]

    def test_env_var_string_level(self):
        os.environ["PULSELOG_LEVEL"] = "ERROR"
        try:
            cfg = Config.load()
            assert cfg.level == "ERROR"
        finally:
            del os.environ["PULSELOG_LEVEL"]

    def test_dumb_term_disables_auto_open(self):
        os.environ["TERM"] = "dumb"
        os.environ.pop("CI", None)
        try:
            cfg = Config.load(auto_open=True)
            assert cfg.auto_open is False
        finally:
            del os.environ["TERM"]

    def test_toml_config_loaded(self, tmp_path, monkeypatch):
        toml = tmp_path / "pulselog.toml"
        toml.write_text('[pulselog]\nport = 7777\n')
        monkeypatch.chdir(tmp_path)
        cfg = Config.load()
        assert cfg.port == 7777

    def test_toml_invalid_falls_back_to_defaults(self, tmp_path, monkeypatch, capsys):
        toml = tmp_path / "pulselog.toml"
        toml.write_bytes(b"\xff\xfe bad toml content \x00")
        monkeypatch.chdir(tmp_path)
        # Should not raise — just warn and use defaults
        cfg = Config.load()
        assert cfg.port == 5678
