import os
from pathlib import Path

import pytest

os.environ.setdefault("LLM_API_KEY", "test-openai-key")
os.environ.setdefault("TTS_API_KEY", "test-tts-key")
os.environ.setdefault("ASR_API_KEY", "test-asr-key")

from app.config import load_settings


def _write_yaml(path: Path, content: str) -> None:
    path.parent.mkdir(parents=True, exist_ok=True)
    path.write_text(content, encoding="utf-8")


def _full_agent_yaml(llm_model: str = "gpt-4o-mini", llm_key: str = "test-openai-key") -> str:
    return f"""
agent:
  vad:
    type: silero
    model_path: data/vad/silero_vad.onnx
    threshold: 0.63
    min_speech_duration_ms: 100
    eou_threshold_ms: 800

  llm:
    provider: openai_compatible
    model: {llm_model}
    temperature: 0.2
    api_key: {llm_key}
    api_url: https://example-llm.invalid/v1

  tts:
    provider: openai_compatible
    api_key: test-tts-key
    api_url: https://example-tts.invalid/v1/audio/speech
    model: FunAudioLLM/CosyVoice2-0.5B
    voice: anna
    speed: 1.0

  asr:
    provider: openai_compatible
    api_key: test-asr-key
    api_url: https://example-asr.invalid/v1/audio/transcriptions
    model: FunAudioLLM/SenseVoiceSmall
    interim_interval_ms: 500
    min_audio_ms: 300
    start_min_speech_ms: 160
    pre_speech_ms: 240
    final_tail_ms: 120

  duplex:
    enabled: true
    system_prompt: You are a strict test assistant.

  barge_in:
    min_duration_ms: 200
    silence_tolerance_ms: 60
""".strip()


def test_cli_profile_loads_agent_yaml(monkeypatch, tmp_path):
    monkeypatch.chdir(tmp_path)
    config_dir = tmp_path / "config" / "agents"
    _write_yaml(
        config_dir / "support.yaml",
        _full_agent_yaml(llm_model="gpt-4.1-mini"),
    )

    settings = load_settings(
        argv=["--agent-profile", "support"],
    )

    assert settings.llm_model == "gpt-4.1-mini"
    assert settings.llm_temperature == 0.2
    assert settings.vad_threshold == 0.63
    assert settings.agent_config_source == "cli_profile"
    assert settings.agent_config_path == str((config_dir / "support.yaml").resolve())


def test_cli_path_has_higher_priority_than_env(monkeypatch, tmp_path):
    monkeypatch.chdir(tmp_path)
    env_file = tmp_path / "config" / "agents" / "env.yaml"
    cli_file = tmp_path / "config" / "agents" / "cli.yaml"

    _write_yaml(env_file, _full_agent_yaml(llm_model="env-model"))
    _write_yaml(cli_file, _full_agent_yaml(llm_model="cli-model"))

    monkeypatch.setenv("AGENT_CONFIG_PATH", str(env_file))

    settings = load_settings(argv=["--agent-config", str(cli_file)])

    assert settings.llm_model == "cli-model"
    assert settings.agent_config_source == "cli_path"
    assert settings.agent_config_path == str(cli_file.resolve())


def test_default_yaml_is_loaded_without_args_or_env(monkeypatch, tmp_path):
    monkeypatch.chdir(tmp_path)
    default_file = tmp_path / "config" / "agents" / "default.yaml"
    _write_yaml(default_file, _full_agent_yaml(llm_model="from-default"))

    monkeypatch.delenv("AGENT_CONFIG_PATH", raising=False)
    monkeypatch.delenv("AGENT_PROFILE", raising=False)

    settings = load_settings(argv=[])

    assert settings.llm_model == "from-default"
    assert settings.agent_config_source == "default"
    assert settings.agent_config_path == str(default_file.resolve())


def test_missing_required_agent_settings_fail(monkeypatch, tmp_path):
    monkeypatch.chdir(tmp_path)
    file_path = tmp_path / "missing-required.yaml"
    _write_yaml(
        file_path,
        """
agent:
  llm:
    model: gpt-4o-mini
""".strip(),
    )

    with pytest.raises(ValueError, match="Missing required agent settings in YAML"):
        load_settings(argv=["--agent-config", str(file_path)])


def test_blank_required_provider_key_fails(monkeypatch, tmp_path):
    monkeypatch.chdir(tmp_path)
    file_path = tmp_path / "blank-key.yaml"
    _write_yaml(file_path, _full_agent_yaml(llm_key=""))

    with pytest.raises(ValueError, match="Missing required agent settings in YAML"):
        load_settings(argv=["--agent-config", str(file_path)])


def test_missing_tts_api_url_fails(monkeypatch, tmp_path):
    monkeypatch.chdir(tmp_path)
    file_path = tmp_path / "missing-tts-url.yaml"
    _write_yaml(
        file_path,
        _full_agent_yaml().replace(
            "    api_url: https://example-tts.invalid/v1/audio/speech\n",
            "",
        ),
    )

    with pytest.raises(ValueError, match="Missing required agent settings in YAML"):
        load_settings(argv=["--agent-config", str(file_path)])


def test_missing_asr_api_url_fails(monkeypatch, tmp_path):
    monkeypatch.chdir(tmp_path)
    file_path = tmp_path / "missing-asr-url.yaml"
    _write_yaml(
        file_path,
        _full_agent_yaml().replace(
            "    api_url: https://example-asr.invalid/v1/audio/transcriptions\n",
            "",
        ),
    )

    with pytest.raises(ValueError, match="Missing required agent settings in YAML"):
        load_settings(argv=["--agent-config", str(file_path)])


def test_agent_yaml_unknown_key_fails(monkeypatch, tmp_path):
    monkeypatch.chdir(tmp_path)
    file_path = tmp_path / "bad-agent.yaml"
    _write_yaml(file_path, _full_agent_yaml() + "\n  unknown_option: true")

    with pytest.raises(ValueError, match="Unknown agent config keys"):
        load_settings(argv=["--agent-config", str(file_path)])


def test_legacy_siliconflow_section_fails(monkeypatch, tmp_path):
    monkeypatch.chdir(tmp_path)
    file_path = tmp_path / "legacy-siliconflow.yaml"
    _write_yaml(
        file_path,
        """
agent:
  siliconflow:
    api_key: x
""".strip(),
    )

    with pytest.raises(ValueError, match="Section 'siliconflow' is no longer supported"):
        load_settings(argv=["--agent-config", str(file_path)])


def test_agent_yaml_missing_env_reference_fails(monkeypatch, tmp_path):
    monkeypatch.chdir(tmp_path)
    file_path = tmp_path / "bad-ref.yaml"
    _write_yaml(
        file_path,
        _full_agent_yaml(llm_key="${UNSET_LLM_API_KEY}"),
    )

    with pytest.raises(ValueError, match="Missing environment variable"):
        load_settings(argv=["--agent-config", str(file_path)])
