import json
from pathlib import Path

import pytest

from pygitweb.config import Settings
from pygitweb.settings_config import init_settings, settings_batch_update, write_settings_file


@pytest.fixture
def settings_path(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> Path:
    path = tmp_path / "settings.json"
    monkeypatch.setenv("PYGITWEB_SETTINGS_CONFIG", str(path))
    monkeypatch.setenv("PYGITWEB_AUTH", "0")
    return path


def test_creates_settings_file_from_environment(settings_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
    monkeypatch.setenv("PYGITWEB_SITE_NAME", "FromEnv")
    settings = init_settings()
    assert settings_path.is_file()
    data = json.loads(settings_path.read_text(encoding="utf-8"))
    assert data["SITE_NAME"] == "FromEnv"
    assert settings.SITE_NAME == "FromEnv"


def test_loads_existing_settings_file(settings_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
    settings_path.write_text(
        json.dumps({
            "PROJECTROOT": "/var/git",
            "PROJECTS_LIST": "/var/git",
            "PROJECT_MAXDEPTH": 2,
            "SITE_NAME": "FromFile",
            "EXPORT_OK": "",
            "LIST_ALL": True,
            "STRICT_EXPORT": False,
            "GIT": "git",
            "MAXLOAD": None,
            "AUTH": False,
            "AUTH_CONFIG": "",
            "SETTINGS_CONFIG": "",
        })
        + "\n",
        encoding="utf-8",
    )
    monkeypatch.delenv("PYGITWEB_SITE_NAME", raising=False)
    settings = init_settings()
    assert settings.SITE_NAME == "FromFile"
    assert settings.PROJECT_MAXDEPTH == 2


def test_env_overrides_settings_file(settings_path: Path, monkeypatch: pytest.MonkeyPatch, capsys) -> None:
    settings_path.write_text(
        json.dumps({
            "PROJECTROOT": "/var/git",
            "PROJECTS_LIST": "/var/git",
            "PROJECT_MAXDEPTH": 1,
            "SITE_NAME": "FromFile",
            "EXPORT_OK": "",
            "LIST_ALL": True,
            "STRICT_EXPORT": False,
            "GIT": "git",
            "MAXLOAD": None,
            "AUTH": False,
            "AUTH_CONFIG": "",
            "SETTINGS_CONFIG": "",
        })
        + "\n",
        encoding="utf-8",
    )
    monkeypatch.setenv("PYGITWEB_SITE_NAME", "FromEnv")
    settings = init_settings()
    assert settings.SITE_NAME == "FromEnv"
    assert json.loads(settings_path.read_text(encoding="utf-8"))["SITE_NAME"] == "FromEnv"
    err = capsys.readouterr().err
    assert "environment overrides settings file" in err
    assert "SITE_NAME" in err


def test_setattr_persists_to_file(settings_path: Path) -> None:
    settings = init_settings()
    settings.SITE_NAME = "Updated"
    assert json.loads(settings_path.read_text(encoding="utf-8"))["SITE_NAME"] == "Updated"


def test_batch_update_persists_once(settings_path: Path) -> None:
    settings = init_settings()
    with settings_batch_update(settings):
        settings.SITE_NAME = "BatchOne"
        settings.GIT = "/usr/bin/git"
    data = json.loads(settings_path.read_text(encoding="utf-8"))
    assert data["SITE_NAME"] == "BatchOne"
    assert data["GIT"] == "/usr/bin/git"


def test_write_settings_file_roundtrip(settings_path: Path) -> None:
    settings = Settings(AUTH=False, SITE_NAME="Roundtrip")
    write_settings_file(settings, settings_path)
    loaded = Settings.model_validate_json(settings_path.read_text(encoding="utf-8"))
    assert loaded.SITE_NAME == "Roundtrip"
    assert loaded.AUTH is False


def test_enabled_plugins_roundtrip(settings_path: Path) -> None:
    settings = init_settings()
    assert settings.ENABLED_PLUGINS == []
    settings.ENABLED_PLUGINS = ["pygitweb_demo", "pygitweb_other"]
    data = json.loads(settings_path.read_text(encoding="utf-8"))
    assert data["ENABLED_PLUGINS"] == ["pygitweb_demo", "pygitweb_other"]
    reloaded = Settings.model_validate_json(settings_path.read_text(encoding="utf-8"))
    assert reloaded.ENABLED_PLUGINS == ["pygitweb_demo", "pygitweb_other"]