"""Tests for DaemonConfig and daemon channel patterns."""

from __future__ import annotations

import pytest

from loom.bus import channels
from loom.config import DaemonConfig, LoomConfig, load_config


# Env vars to clear so host environment doesn't leak.
_DAEMON_ENV_VARS = (
    "LOOM_DAEMON_ENABLED",
    "LOOM_DAEMON_TICK_INTERVAL",
    "LOOM_DAEMON_PID_FILE",
    "LOOM_DAEMON_LOG_FILE",
)

# Also clear vars that affect config loading generally.
_ALL_ENV_VARS = _DAEMON_ENV_VARS + (
    "LOOM_DATABASE_URL",
    "LOOM_REDIS_URL",
    "LOOM_PROJECT_ID",
    "LOOM_LOG_LEVEL",
)


@pytest.fixture(autouse=True)
def _clean_env(monkeypatch, tmp_path):
    """Remove Loom env vars and point HOME to tmp so no host YAML leaks."""
    for var in _ALL_ENV_VARS:
        monkeypatch.delenv(var, raising=False)
    monkeypatch.setenv("HOME", str(tmp_path))


# --- DaemonConfig model defaults ---


class TestDaemonConfigDefaults:
    def test_defaults(self):
        cfg = DaemonConfig()
        assert cfg.enabled is False
        assert cfg.tick_interval_seconds == 30
        assert cfg.pid_file_path == ".loom/daemon.pid"
        assert cfg.log_file_path == ".loom/logs/daemon.log"

    def test_embedded_in_loom_config(self):
        cfg = LoomConfig()
        assert isinstance(cfg.daemon, DaemonConfig)
        assert cfg.daemon.enabled is False

    def test_custom_values(self):
        cfg = DaemonConfig(
            enabled=True,
            tick_interval_seconds=10,
            pid_file_path="/var/run/loom.pid",
            log_file_path="/var/log/loom-daemon.log",
        )
        assert cfg.enabled is True
        assert cfg.tick_interval_seconds == 10
        assert cfg.pid_file_path == "/var/run/loom.pid"
        assert cfg.log_file_path == "/var/log/loom-daemon.log"


# --- Environment variable overrides ---


class TestDaemonEnvVarOverrides:
    def test_enabled_override(self, monkeypatch):
        monkeypatch.setenv("LOOM_DAEMON_ENABLED", "true")
        cfg = load_config(project_dir=None)
        assert cfg.daemon.enabled is True

    def test_enabled_override_yes(self, monkeypatch):
        monkeypatch.setenv("LOOM_DAEMON_ENABLED", "yes")
        cfg = load_config(project_dir=None)
        assert cfg.daemon.enabled is True

    def test_enabled_override_false(self, monkeypatch):
        monkeypatch.setenv("LOOM_DAEMON_ENABLED", "false")
        cfg = load_config(project_dir=None)
        assert cfg.daemon.enabled is False

    def test_tick_interval_override(self, monkeypatch):
        monkeypatch.setenv("LOOM_DAEMON_TICK_INTERVAL", "15")
        cfg = load_config(project_dir=None)
        assert cfg.daemon.tick_interval_seconds == 15

    def test_pid_file_override(self, monkeypatch):
        monkeypatch.setenv("LOOM_DAEMON_PID_FILE", "/tmp/loom.pid")
        cfg = load_config(project_dir=None)
        assert cfg.daemon.pid_file_path == "/tmp/loom.pid"

    def test_log_file_override(self, monkeypatch):
        monkeypatch.setenv("LOOM_DAEMON_LOG_FILE", "/tmp/loom-daemon.log")
        cfg = load_config(project_dir=None)
        assert cfg.daemon.log_file_path == "/tmp/loom-daemon.log"


# --- YAML config loading ---


class TestDaemonYamlConfig:
    def test_yaml_daemon_section(self, tmp_path):
        """DaemonConfig loaded from project YAML."""
        loom_dir = tmp_path / ".loom"
        loom_dir.mkdir()
        (loom_dir / "config.yaml").write_text(
            "daemon:\n"
            "  enabled: true\n"
            "  tick_interval_seconds: 45\n"
            "  pid_file_path: custom/daemon.pid\n"
            "  log_file_path: custom/daemon.log\n"
        )
        cfg = load_config(project_dir=str(tmp_path))
        assert cfg.daemon.enabled is True
        assert cfg.daemon.tick_interval_seconds == 45
        assert cfg.daemon.pid_file_path == "custom/daemon.pid"
        assert cfg.daemon.log_file_path == "custom/daemon.log"

    def test_yaml_without_daemon_section(self, tmp_path):
        """Config works fine when no daemon section in YAML."""
        loom_dir = tmp_path / ".loom"
        loom_dir.mkdir()
        (loom_dir / "config.yaml").write_text(
            "loom:\n  project_name: test\n"
        )
        cfg = load_config(project_dir=str(tmp_path))
        assert cfg.daemon.enabled is False
        assert cfg.daemon.tick_interval_seconds == 30

    def test_env_overrides_yaml(self, monkeypatch, tmp_path):
        """Env vars take precedence over YAML."""
        loom_dir = tmp_path / ".loom"
        loom_dir.mkdir()
        (loom_dir / "config.yaml").write_text(
            "daemon:\n  tick_interval_seconds: 45\n"
        )
        monkeypatch.setenv("LOOM_DAEMON_TICK_INTERVAL", "10")
        cfg = load_config(project_dir=str(tmp_path))
        assert cfg.daemon.tick_interval_seconds == 10


# --- Channel pattern functions ---


class TestDaemonChannelPatterns:
    def test_daemon_inbox(self):
        key = channels.daemon_inbox("proj-123")
        assert key == "loom:proj-123:daemon:inbox"

    def test_daemon_health(self):
        key = channels.daemon_health("proj-123")
        assert key == "loom:proj-123:daemon:health"

    def test_daemon_inbox_different_projects(self):
        """Each project gets its own inbox stream."""
        k1 = channels.daemon_inbox("proj-a")
        k2 = channels.daemon_inbox("proj-b")
        assert k1 != k2
        assert "proj-a" in k1
        assert "proj-b" in k2
