"""Installer bootstrap: --init-config / init_config_file."""
from __future__ import annotations

import tomllib

from app.auth import init_config_file


def test_creates_toml_with_key_host_port(tmp_path):
    path = tmp_path / "server.toml"
    assert init_config_file(path, "0.0.0.0", 9123) is True
    data = tomllib.loads(path.read_text(encoding="utf-8"))
    assert data["host"] == "0.0.0.0"
    assert data["port"] == 9123
    assert data["api_key"].startswith("vxc_") and len(data["api_key"]) == 36
    assert data["model"] == "auto"
    assert data["device"] == "auto"


def test_existing_config_is_never_touched(tmp_path):
    path = tmp_path / "server.toml"
    path.write_text('api_key = "vxc_keepme"\nport = 7777\n', encoding="utf-8")
    assert init_config_file(path, "0.0.0.0", 8590) is False
    data = tomllib.loads(path.read_text(encoding="utf-8"))
    assert data["api_key"] == "vxc_keepme"
    assert data["port"] == 7777


def test_generated_keys_are_unique(tmp_path):
    a, b = tmp_path / "a.toml", tmp_path / "b.toml"
    init_config_file(a, "0.0.0.0", 8590)
    init_config_file(b, "0.0.0.0", 8590)
    ka = tomllib.loads(a.read_text(encoding="utf-8"))["api_key"]
    kb = tomllib.loads(b.read_text(encoding="utf-8"))["api_key"]
    assert ka != kb


def test_init_config_cli(tmp_path, monkeypatch, capsys):
    """The exe entrypoint writes the file at config_file_path() and exits 0."""
    import server_main
    cfg = tmp_path / "server.toml"
    monkeypatch.setenv("VOXCAST_SERVER_CONFIG", str(cfg))
    rc = server_main._init_config(
        ["--init-config", "--host", "0.0.0.0", "--port", "9001"])
    assert rc == 0
    data = tomllib.loads(cfg.read_text(encoding="utf-8"))
    assert data["port"] == 9001
    out = capsys.readouterr().out
    assert "created" in out
    assert "vxc_" not in out  # never print the key


def test_init_config_cli_invalid_port_falls_back(tmp_path, monkeypatch):
    import server_main
    cfg = tmp_path / "server.toml"
    monkeypatch.setenv("VOXCAST_SERVER_CONFIG", str(cfg))
    server_main._init_config(["--init-config", "--port", "99999"])
    data = tomllib.loads(cfg.read_text(encoding="utf-8"))
    assert data["port"] == 8590


# ── operator-supplied API key ───────────────────────────────────────────────

def test_custom_api_key_is_used(tmp_path):
    from app.auth import init_config_file
    path = tmp_path / "server.toml"
    init_config_file(path, "0.0.0.0", 8590, api_key="my-lan-key_2026")
    data = tomllib.loads(path.read_text(encoding="utf-8"))
    assert data["api_key"] == "my-lan-key_2026"


def test_invalid_custom_key_falls_back_to_generated(tmp_path):
    from app.auth import init_config_file
    for bad in ("short", "has spaces", 'has"quote', "x" * 200):
        path = tmp_path / f"s_{len(bad)}_{bad[:3]}.toml"
        init_config_file(path, "0.0.0.0", 8590, api_key=bad)
        data = tomllib.loads(path.read_text(encoding="utf-8"))
        assert data["api_key"].startswith("vxc_")


def test_sanitize_api_key():
    from app.auth import sanitize_api_key
    assert sanitize_api_key("Good_Key-123") == "Good_Key-123"
    assert sanitize_api_key("  spaced  ") == ""   # inner space illegal after strip? trims only ends
    assert sanitize_api_key("short") == ""
    assert sanitize_api_key('bad"quote') == ""
    assert sanitize_api_key("x" * 129) == ""


# ── model selection at install + --set-model ────────────────────────────────

def test_init_config_model(tmp_path):
    from app.auth import init_config_file
    path = tmp_path / "server.toml"
    init_config_file(path, "0.0.0.0", 8590, model="large-v3-turbo")
    data = tomllib.loads(path.read_text(encoding="utf-8"))
    assert data["model"] == "large-v3-turbo"


def test_init_config_unknown_model_falls_back(tmp_path):
    from app.auth import init_config_file
    path = tmp_path / "server.toml"
    init_config_file(path, "0.0.0.0", 8590, model="gpt5")
    data = tomllib.loads(path.read_text(encoding="utf-8"))
    assert data["model"] == "auto"


def test_set_config_model_rewrites_existing(tmp_path):
    from app.auth import init_config_file, set_config_model
    path = tmp_path / "server.toml"
    init_config_file(path, "0.0.0.0", 8590, model="small")
    applied = set_config_model(path, "medium")
    assert applied == "medium"
    data = tomllib.loads(path.read_text(encoding="utf-8"))
    assert data["model"] == "medium"
    # untouched fields survive
    assert data["port"] == 8590
    assert data["api_key"].startswith("vxc_")


def test_set_config_model_rejects_unknown(tmp_path):
    import pytest
    from app.auth import init_config_file, set_config_model
    path = tmp_path / "server.toml"
    init_config_file(path, "0.0.0.0", 8590)
    with pytest.raises(ValueError):
        set_config_model(path, "turbo9000")


def test_set_config_model_missing_file(tmp_path):
    import pytest
    from app.auth import set_config_model
    with pytest.raises(FileNotFoundError):
        set_config_model(tmp_path / "nope.toml", "medium")


def test_set_model_cli(tmp_path, monkeypatch, capsys):
    import server_main
    from app.auth import init_config_file
    cfg = tmp_path / "server.toml"
    monkeypatch.setenv("VOXCAST_SERVER_CONFIG", str(cfg))
    init_config_file(cfg, "0.0.0.0", 8590, model="small")
    rc = server_main._set_model(["--set-model", "large-v3-turbo"])
    assert rc == 0
    assert tomllib.loads(cfg.read_text(encoding="utf-8"))["model"] == "large-v3-turbo"
    assert "Restart" in capsys.readouterr().out


# ── prompt-management CLI + update CLI ──────────────────────────────────────

def test_prompts_cli_add_list_remove(tmp_path, monkeypatch, capsys):
    import server_main
    monkeypatch.setenv("VOXCAST_DATA_DIR", str(tmp_path))
    assert server_main._prompts_cli(["--add-prompt", "Reply", "Write a reply."]) == 0
    assert "Saved prompt" in capsys.readouterr().out
    server_main._prompts_cli(["--list-prompts"])
    out = capsys.readouterr().out
    assert "reply" in out and "Write a reply." in out
    assert server_main._prompts_cli(["--remove-prompt", "reply"]) == 0
    assert server_main._prompts_cli(["--remove-prompt", "reply"]) == 1


def test_prompts_cli_custom_id(tmp_path, monkeypatch, capsys):
    import server_main
    import tomllib  # noqa: F401 (ensure stdlib present)
    monkeypatch.setenv("VOXCAST_DATA_DIR", str(tmp_path))
    server_main._prompts_cli(["--add-prompt", "My Mode", "text", "--id", "custom"])
    from app import prompts as pm
    assert pm.load_prompts(tmp_path)[0]["id"] == "custom"
