"""Tests for app.utils.jail_config.ensure_jail_configs."""

from __future__ import annotations

from pathlib import Path

from app.utils.jail_config import (
    _BLOCKLIST_IMPORT_CONF,
    _BLOCKLIST_IMPORT_LOCAL,
    _MANUAL_JAIL_CONF,
    _MANUAL_JAIL_LOCAL,
    ensure_jail_configs,
)

# ---------------------------------------------------------------------------
# Expected filenames
# ---------------------------------------------------------------------------

_MANUAL_CONF = "manual-Jail.conf"
_MANUAL_LOCAL = "manual-Jail.local"
_BLOCKLIST_CONF = "blocklist-import.conf"
_BLOCKLIST_LOCAL = "blocklist-import.local"

_ALL_FILES = [_MANUAL_CONF, _MANUAL_LOCAL, _BLOCKLIST_CONF, _BLOCKLIST_LOCAL]

_CONTENT_MAP: dict[str, str] = {
    _MANUAL_CONF: _MANUAL_JAIL_CONF,
    _MANUAL_LOCAL: _MANUAL_JAIL_LOCAL,
    _BLOCKLIST_CONF: _BLOCKLIST_IMPORT_CONF,
    _BLOCKLIST_LOCAL: _BLOCKLIST_IMPORT_LOCAL,
}


# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------


def _read(jail_d: Path, filename: str) -> str:
    return (jail_d / filename).read_text(encoding="utf-8")


# ---------------------------------------------------------------------------
# Tests: ensure_jail_configs
# ---------------------------------------------------------------------------


class TestEnsureJailConfigs:
    def test_all_missing_creates_all_four(self, tmp_path: Path) -> None:
        """All four files are created when the directory is empty."""
        jail_d = tmp_path / "jail.d"
        ensure_jail_configs(jail_d)

        for name in _ALL_FILES:
            assert (jail_d / name).exists(), f"{name} should have been created"
            assert _read(jail_d, name) == _CONTENT_MAP[name]

    def test_all_missing_creates_correct_content(self, tmp_path: Path) -> None:
        """Each created file has exactly the expected default content."""
        jail_d = tmp_path / "jail.d"
        ensure_jail_configs(jail_d)

        # .conf files must set enabled = false
        for conf_file in (_MANUAL_CONF, _BLOCKLIST_CONF):
            content = _read(jail_d, conf_file)
            assert "enabled    = false" in content

        # Blocklist-import jail must have a 24-hour ban time
        blocklist_conf = _read(jail_d, _BLOCKLIST_CONF)
        assert "bantime    = 86400" in blocklist_conf

        # .local files must set enabled = true and nothing else
        for local_file in (_MANUAL_LOCAL, _BLOCKLIST_LOCAL):
            content = _read(jail_d, local_file)
            assert "enabled    = true" in content

    def test_all_present_overwrites_nothing(self, tmp_path: Path) -> None:
        """Existing files are never overwritten."""
        jail_d = tmp_path / "jail.d"
        jail_d.mkdir()

        sentinel = "# EXISTING CONTENT — must not be replaced\n"
        for name in _ALL_FILES:
            (jail_d / name).write_text(sentinel, encoding="utf-8")

        ensure_jail_configs(jail_d)

        for name in _ALL_FILES:
            assert _read(jail_d, name) == sentinel, (
                f"{name} should not have been overwritten"
            )

    def test_only_local_files_missing_creates_only_locals(
        self, tmp_path: Path
    ) -> None:
        """Only the .local files are created when the .conf files already exist."""
        jail_d = tmp_path / "jail.d"
        jail_d.mkdir()

        sentinel = "# pre-existing conf\n"
        for conf_file in (_MANUAL_CONF, _BLOCKLIST_CONF):
            (jail_d / conf_file).write_text(sentinel, encoding="utf-8")

        ensure_jail_configs(jail_d)

        # .conf files must remain unchanged
        for conf_file in (_MANUAL_CONF, _BLOCKLIST_CONF):
            assert _read(jail_d, conf_file) == sentinel

        # .local files must have been created with correct content
        for local_file, expected in (
            (_MANUAL_LOCAL, _MANUAL_JAIL_LOCAL),
            (_BLOCKLIST_LOCAL, _BLOCKLIST_IMPORT_LOCAL),
        ):
            assert (jail_d / local_file).exists(), f"{local_file} should have been created"
            assert _read(jail_d, local_file) == expected

    def test_creates_jail_d_directory_if_missing(self, tmp_path: Path) -> None:
        """The jail.d directory is created automatically when absent."""
        jail_d = tmp_path / "nested" / "jail.d"
        assert not jail_d.exists()
        ensure_jail_configs(jail_d)
        assert jail_d.is_dir()

    def test_idempotent_on_repeated_calls(self, tmp_path: Path) -> None:
        """Calling ensure_jail_configs twice does not alter any file."""
        jail_d = tmp_path / "jail.d"
        ensure_jail_configs(jail_d)

        # Record content after first call
        first_pass = {name: _read(jail_d, name) for name in _ALL_FILES}

        ensure_jail_configs(jail_d)

        for name in _ALL_FILES:
            assert _read(jail_d, name) == first_pass[name], (
                f"{name} changed on second call"
            )
