"""Tests for loom doctor command (Stream C)."""

import json
import subprocess
from pathlib import Path
from unittest.mock import patch, MagicMock

from click.testing import CliRunner

from loom.cli import cli


def test_doctor_command_exists():
    """loom doctor command is registered."""
    runner = CliRunner()
    result = runner.invoke(cli, ["doctor", "--help"])
    assert result.exit_code == 0
    assert "health" in result.output.lower() or "Check" in result.output


def test_doctor_no_init(tmp_path, monkeypatch):
    """Doctor reports missing initialization."""
    monkeypatch.chdir(tmp_path)
    runner = CliRunner()
    result = runner.invoke(cli, ["doctor"])
    assert "loom init" in result.output.lower() or "✗" in result.output


def test_doctor_no_docker(tmp_path, monkeypatch):
    """Doctor reports Docker not running."""
    monkeypatch.chdir(tmp_path)
    with patch("subprocess.run") as mock_run:
        mock_run.return_value = MagicMock(returncode=1)
        runner = CliRunner()
        result = runner.invoke(cli, ["doctor"])
        assert "Docker" in result.output or "docker" in result.output.lower()


def test_doctor_all_pass(tmp_path, monkeypatch):
    """Doctor reports all checks pass when everything is configured."""
    monkeypatch.chdir(tmp_path)

    # Create .loom/config.yaml
    loom_dir = tmp_path / ".loom"
    loom_dir.mkdir()
    config = {
        "loom": {"project_name": "test", "project_id": "00000000-0000-0000-0000-000000000001"},
        "database": {"url": "postgresql://loom:loom@localhost:5432/loom"},
        "redis": {"url": "redis://localhost:6379"},
    }
    import yaml
    with open(loom_dir / "config.yaml", "w") as f:
        yaml.dump(config, f)

    # Create docker-compose.loom.yml
    with open(tmp_path / "docker-compose.loom.yml", "w") as f:
        f.write("services: {}")

    # Create .mcp.json with loom entry
    mcp_data = {"mcpServers": {"loom": {"command": "uv", "args": []}}}
    with open(tmp_path / ".mcp.json", "w") as f:
        json.dump(mcp_data, f)

    # Set API key
    monkeypatch.setenv("ANTHROPIC_API_KEY", "test-key")

    # Mock subprocess (Docker), postgres, redis, migrations, project
    with patch("subprocess.run") as mock_run, \
         patch("loom.cli._check_postgres", return_value=True), \
         patch("loom.cli._check_redis", return_value=True), \
         patch("loom.cli._check_migrations", return_value=True), \
         patch("loom.cli._check_project", return_value=True):
        mock_run.return_value = MagicMock(returncode=0)

        runner = CliRunner()
        result = runner.invoke(cli, ["doctor"])
        assert "All checks passed" in result.output


def test_doctor_missing_api_key(tmp_path, monkeypatch):
    """Doctor shows warning (not error) for missing API key."""
    monkeypatch.chdir(tmp_path)
    monkeypatch.delenv("ANTHROPIC_API_KEY", raising=False)
    monkeypatch.delenv("OPENAI_API_KEY", raising=False)
    monkeypatch.delenv("LOOM_SKILLS_API_KEY", raising=False)

    runner = CliRunner()
    result = runner.invoke(cli, ["doctor"])
    # API key should be a warning, not a hard failure
    assert "optional" in result.output.lower() or "!" in result.output


def test_doctor_postgres_failure(tmp_path, monkeypatch):
    """Doctor reports Postgres connection failure."""
    monkeypatch.chdir(tmp_path)

    # Create minimal init
    loom_dir = tmp_path / ".loom"
    loom_dir.mkdir()
    import yaml
    config = {
        "loom": {"project_name": "test", "project_id": "00000000-0000-0000-0000-000000000001"},
        "database": {"url": "postgresql://loom:loom@localhost:59999/loom"},  # bad port
        "redis": {"url": "redis://localhost:6379"},
    }
    with open(loom_dir / "config.yaml", "w") as f:
        yaml.dump(config, f)

    with open(tmp_path / "docker-compose.loom.yml", "w") as f:
        f.write("services: {}")

    with patch("subprocess.run") as mock_run:
        mock_run.return_value = MagicMock(returncode=0)
        runner = CliRunner()
        result = runner.invoke(cli, ["doctor"])
        # Should show postgres failure
        assert "Postgres" in result.output or "loom up" in result.output
